GIT repositories

Index page of all the GIT repositories that are clonable form this server via HTTPS. Übersichtsseite aller GIT-Repositories, die von diesem Server aus über git clone (HTTPS) erreichbar sind.

Services

A bunch of service scripts to convert, analyse and generate data. Ein paar Services zum Konvertieren, Analysieren und Generieren von Daten.

GNU octave web interface

A web interface for GNU Octave, which allows to run scientific calculations from netbooks, tables or smartphones. The interface provides a web form generator for Octave script parameters with pre-validation, automatic script list generation, as well presenting of output text, figures and files in a output HTML page. Ein Webinterface für GNU-Octave, mit dem wissenschaftliche Berechnungen von Netbooks, Tablets oder Smartphones aus durchgeführt werden können. Die Schnittstelle beinhaltet einen Formulargenerator für Octave-Scriptparameter, mit Einheiten und Einfabevalidierung. Textausgabe, Abbildungen und generierte Dateien werden abgefangen und in einer HTML-Seite dem Nutzer als Ergebnis zur Verfügung gestellt.

C Programm zum ausführen eines Shell-Befehls als root ohne Passworteingabe

C program to run a shell command as root without password

In some situations specific programs need to be executed with root user permissions, even if the current user has no rights to run sudo. If no way around this problem using conventional user/group management can be found, the "workaround C source code" shown below can help. Compiling this source using gcc will enable to pass a program as first argument, which will run under root. Some built-in restrictions and precautions are:

  • The compiled program must be owned by root (including group root).
  • The compiled program must not be a link, writable or readable by anyone else.
  • The SETUID flag must be set for compiled program (see example below).
  • The child program (passed as 1st argument) must be owned by root as well.
  • The child program must not be readable or writable by anyone else.
  • The path to the child program must be either a full path (/...) or a relative path prefixed with ./.

The compiled program passes the command line arguments to the child program, passes through STDOUT and STDERR and returns the exit code of the child program.

Again: Before applying this method, check if sudo or appropriate user/group management does the job. It is not wise and very likely insecure to enable running programs/scripts as root.

In manchen Situationen kommt man nicht umher bestimmte Programme mit root-Rechten auszuführen, ohne dass der aktuelle Nutzer diese erhalten kann (z.B. nicht in sudoers). Wenn keine andere Möglichkeit gefunden wird dieses Problem durch Nutzer-/Gruppenmanagement zu umgehen, so kann dieser "Workaround C Quelltext" vielleicht helfen. Wenn der unten angegebene Source Code (mit gcc -Wall runsu.c -o runsu) compiliert wird, so erlaubt runsu ein Programm als root auszuführen. Ein paar Vorprüfungen, um die Sicherheit etwas zu erhöhen sind:

  • Das compilierte Programm muss dem Nutzer root (und Gruppe root) gehören,
  • Es darf von sonst keinem lesbar oder schreibbar sein,
  • Das SETUID flag muss gesetzt sein (siehe unten).
  • Das auzuführende Programm muss ebenfalls root gehören und darf weder lesbar noch schreibbar von anderen sein.
  • Der Pfad zum auszuführenden Programm muss entweder vollständig angegeben werden (/...) oder relativ mit dem Prefix ./.

Das kompilierte Programm reicht die Kommandozeilenargumente an das auszuführende Programm weiter, reicht dessen STDOUT und STDERR zurück und beendet mit dem selben Exit-Code wie das ausgeführte Programm.

Nochmals: Bevor zu dieser Methode gegriffen wird sollte wirklich nochmals geprüft werden, ob sudo oder Nutzermanagement Abhilfe schaffen kann. Es is meist keine gute Idee Programme ohne Passwortangabe als root auszuführen.

Installation / test

Installation / Test

# Compile ...
gcc -Wall runsu.c -o runsu
sudo chown root:root runsu
sudo chmod u=rwxs,g=sx,o=sx runsu
# sudo mv runsu /usr/local/bin/ <<<<< ... if you like ...

# Example child program: Shell script with 'whoami'
echo -e '#!/bin/sh\necho I am $(whoami)\necho args=$@\n' > test.sh
sudo chown root:root test.sh
sudo chmod 700 test.sh

#run:
$ ./runsu ./test.sh --a --b --c
I am root                       <<<<< ... double check this ...
args=--a --b --c

Sorce code

Quelltext

/**
 * Define this to set a fixed command to execute.
 * The shell command line preparation below does NOT
 * escape this command, but the arguments passed through
 * form the command line.
 *
 * #define FIXED_COMMAND "/usr/bin/something -a -r -g --arg file1 file2 ..."
 * #define NO_ARGS 1
 *
 * OR
 *
 * gcc -Wall runsu.c -o runsu -DNO_ARGS=1
 *
 * gcc -Wall runsu.c -o runsu -DFIXED_COMMAND='/bin/ls -lsia /dev/ *'
 *
 * -------------------------------------------------------------------------
 *
 * NOTES: - This source code is published "as is", no warranties are
 *          granted.
 *        - It is only in special cases wise to run programs as root,
 *          especially if no password is required. Consider using `sudo`
 *          (maybe editing /etc/sudoers` as well) before using the method
 *          shown here!
 *        - Consider defining fixed commands using precompiler flags instead
 *          of passing program- or script paths as argument.
 *
 * @file runsu.c
 * @license GPL2
 * @author stfwi
 */
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
 
#ifndef NO_ARGS
#define NO_ARGS (0)
#endif
#ifndef FIXED_COMMAND
#define HAS_FIXED_COMMAND (0)
#define FIXED_COMMAND ""
#else
#define HAS_FIXED_COMMAND (1)
#endif
 
int main(int argc, char** argv)
{
  struct stat st;
  int euid = getuid(), status = -1, i, is_help = 0;
  char line[512], *ps, *pl;
  const char *child;
 
  #if !HAS_FIXED_COMMAND
    child = (const char *) (((argc >= 2) && argv[1]) ? argv[1] : NULL);
    is_help = child && ((!strcmp(child, "-h")) || (!strcmp(child, "--help")));
  #else
    child = FIXED_COMMAND;
    is_help = 0;
  #endif
  #if NO_ARGS
    if (argc > (HAS_FIXED_COMMAND ? 1 : 2)) {
      fprintf(stderr, "No arguments allowed (defined as compiler flag)\n\n");
      exit(-1);
    }
  #endif
 
  /* HELP */
  if (!child || is_help) {
    if (!child) fprintf(stderr, "No program specified to run.\n");
    fprintf(stderr, "Usage: %s <program to run> [arguments]\n\n", argv[0]);
    fprintf(stderr, "  Runs a program or script as root. This script must\n");
    fprintf(stderr, "  be owned by user 'root' and group 'root', and not\n");
    fprintf(stderr, "  readable, writable or executable by anyone else.\n");
    fprintf(stderr, "  This program must be owned by root:root as well,\n");
    fprintf(stderr, "  not readable or writable by others (neither the group)\n");
    fprintf(stderr, "  and the SETUID bit must be set:\n");
    fprintf(stderr, "  (`chmod u=rwxs,g=sx,o=sx '%s'`)\n", argv[0]);
    fprintf(stderr, "  The program passes through STDOUT and STDERR, and\n");
    fprintf(stderr, "  returns the exit code of the executed child program.\n");
    fprintf(stderr, "\n");
    fprintf(stderr, "  (compiler settings: %s%s)\n", NO_ARGS ? "no arguments allowed,"
        : "", HAS_FIXED_COMMAND ? ("command=" FIXED_COMMAND) : "");
    exit(-1);
  /* CHECK MY OWN PERMISSIONS */
  } else if (!argv[0] || stat(argv[0], &st)) {
    fprintf(stderr, "Failed to get permissions of this program.\n");
    exit(-1);
  } else if (st.st_gid || st.st_uid) {
    fprintf(stderr, "This program file must be owned by root (and group root)."
        " Use chown root:root '%s'\n", argv[0]);
    exit(-1);
  } else if (!(st.st_mode & (S_IFREG | S_IRWXU | S_ISUID)) ||
      (st.st_mode & (S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH))) {
    fprintf(stderr, "This program file must have the permissions \"-rws--s--x\"."
        " Use chmod u=rwxs,g=sx,o=sx '%s'\n", argv[0]);
    exit(-1);
  /* CHECK CHILD PROGRAM PERMISSIONS */
  #if !HAS_FIXED_COMMAND
  } else if (!child || stat(child, &st)) {
    fprintf(stderr, "Failed to get permissions of '%s'.\n", child ? child : "(NULL)");
    exit(-1);
  } else if (st.st_gid || st.st_uid) {
    fprintf(stderr, "The program to run must be owned by root (and group root)."
        "Use chown root:root '%s'\n", child);
    exit(-1);
  } else if (!(st.st_mode & S_IFREG)) {
    fprintf(stderr, "The program to run must not be a link\n");
    exit(-1);
  } else if (st.st_mode & (S_IRGRP | S_IWGRP)) {
    fprintf(stderr, "The program to run must not be readable or writable by other"
        "users than root (\"-rwx------\"). Use chmod 700 '%s'\n", child);
    exit(-1);
  #endif
  /* DOUBLE CHECK CHILD PROGRAM PATH */
  } else if (child[0] != '/' && strstr(child, "./") != child) {
    fprintf(stderr, "The path of the program to run must be specified as full path"
        " (e.g. /usr/bin/...) or as relative path starting with './'\n");
    exit(-1);
  /* SWITCH USER TO ROOT */
  } else if (setuid(0) < 0) {
    fprintf(stderr, "Failed to switch to root user (setuid()<0)'\n");
    exit(-1);
  /* REMOVE ALL ENVIRONMENT INFORMATION */
  } else if (clearenv()) {
    setuid(euid);
    fprintf(stderr, "Failed remove the envoronment before executing the program'\n");
    exit(-1);
  }
 
  /* BUILD COMMAND LINE, ENCLOSE AND ESCAPE "'" */
  #define PLOK (pl < (line+(sizeof(line)/sizeof(char))-1))
  memset(line, 0, sizeof (line) / sizeof (char));
  #if HAS_FIXED_COMMAND
    strncpy(line, child, (sizeof (line) / sizeof (char)) - 1);
    pl = line + strlen(line);
    *pl++ = ' ';
  #else
    pl = line;
  #endif
 
  for (i = 1; i < argc && argv[i] && PLOK; i++) {
    *pl++ = '\'';
    if (!PLOK) break;
    for (ps = argv[i]; ps && *ps && PLOK; ps++) {
      if (*ps == '\'') {
        *pl++ = '\'';
        if (!PLOK) break;
        *pl++ = '\\';
        if (!PLOK) break;
        *pl++ = '\'';
        if (!PLOK) break;
        *pl++ = '\'';
        if (!PLOK) break;
      }
      if (!PLOK || !ps || !*ps) break;
      *pl++ = *ps;
      if (!PLOK) break;
    }
    *pl++ = '\'';
    if (!PLOK) break;
    *pl++ = ' ';
    if (!PLOK) break;
  }
  if (!PLOK) {
    setuid(euid);
    fprintf(stderr, "Command line is too long.'\n");
    exit(-1);
  } else if (pl == line || strlen(line) == 0) {
    setuid(euid);
    fprintf(stderr, "Unexpected short command line (--> BUG).'\n");
    exit(-1);
  } else if (line[strlen(line) - 1] == ' ') {
    line[strlen(line) - 1] = '\0';
  }
  #undef PLOK
  status = system(line);
  setuid(euid);
  return WEXITSTATUS(status);
}