Programmer’s Toolbox - Dateien, Teil 15: Einige Kommandos zur Benutzerverwaltung

In der heutigen, letzten Folge der Programmer’s Toolbox werden vier Kommandos implementiert, die eine Benutzerverwaltung mit Paßwortschutz realisieren. Im einzelnen handelt es sich dabei um folgende Kommandos:

MKUSER - Anlegen eines Benutzerdatensatzes
RMUSER - Löschen eines Benutzerdatensatzes
PASSWD - Ändern von Paßwörtern
LOGIN - Einloggen in das System

Die Kommandos basieren auf den beiden in der letzten Ausgabe abgedruckten Modulen CRYPT und USERMAIN.

Name
MKUSER - Erzeugen eines Benutzerdatensatzes

Anwendung
MKUSER Benutzer [Shell]

Beschreibung
Für den Benutzer wird ein neuer Benutzerdatensatz angelegt oder ein bestehender überschrieben. Sie werden in der Textdatei\BIN\PASSWD gespeichert. Jeder Benutzerdatensatz besteht dabei aus:

Der Benutzername und das Paßwort werden benötigt, um den Benutzer gegenüber dem System zu identifizieren. Nach einer erfolgreichen Identifizierung (Kommando LOGIN) bekommt ein Benutzer Zugang zum System. Der Eintrag Shell innerhalb des Benutzerdatensatzes gibt dabei an, welches Kommando beim Systemzugang zu starten ist.

Mit dem Kommando MKUSER wird mindestens der Benutzername über den Parameter Benutzer festgelegt. Optional läßt sich eine Shell, also ein Programm, das beim Systemzugang gestartet wird, eingeben. Zunächst wird nur ein leeres Paßwort eingetragen. Fehlt der Shell-Parameter, wird \BIN\SSH.TTP, also die Simple Shell, die wir innerhalb dieser Serie entwickelt haben, als Standardeinstellung eingetragen.

Beispiel
Die Datei \BIN\PASSWD kann nach einigen Aufrufen von MKUSER und PASSWD (Ändern eines Paßworts) etwa folgendermaßen aussehen:

maxon | ]dOAF25fNmzVU | \BIN\SSH.TTP text | xewoVkdly8ua. |
\WORD\WORDPLUS.PRG
list | ohne | \BIN\LS.TTP
brockhaus | mrZ8IwOXB2Tg2 |
\BIN\SSH.TTP

Wie Sie sehen, ist es nicht unbedingt erforderlich, daß SSH.TTP als Shell verwendet wird.

Implementierung
Die Implementierung des Kommandos MKUSER (Listing 3.8) läßt sich mit Hilfe der Funktionen des Moduls USERMAIN leicht bewerkstelligen. Innerhalb der Funktion mkuser (Zeilen 44-51) findet man die entsprechenden Aufrufe von Funktionen dieses Moduls.

Name
RMUSER - Löschen eines Benutzerdatensatzes

Anwendung
RMUSER Benutzer

Beschreibung
Mit dem Kommando RMUSER wird der Eintrag für Benutzer aus der Datei \BIN\PASSWD entfernt. Der Benutzer besitzt danach keine Berechtigung zum Systemzugang mehr.

Implementierung

Die Implementierung des Kommandos RMUSER (Listing 3.9) ist weitgehend selbstdokumentierend, da der zentrale Bereich (Funktion rmuser, Zeilen 34-36 ausschließlich aus Funktionsaufrufen des Moduls USERMAIN besteht.

Name
PASSWD - Ändern von Paßwörtern

Anwendung
PASSWD Benutzer

Beschreibung
Nach Anlegen des Benutzerdatensatzes mit dem Kommando MKUSER kann man mit PASSWD ein Paßwort für den Benutzer eintragen. Als Parameter wird der Benutzername erwartet. Die Eingabe des Paßworts erfolgt interaktiv und ohne Echo auf der Konsole. Es wird zunächst zweimal das alte Paßwort abgefragt, danach zweimal das neue. Die Doppelabfrage soll sicherstellen, daß trotz des fehlenden Echos eine korrekte Eingabe erfolgt ist.

Wenn alle Eingaben zufriedenstellend erfolgt sind, wird das neue Paßwort mit der in der letzten Folge vorgestellten Funktion crypt verschlüsselt und in die Datei \BIN\PASSWD eingetragen. Die Aufgabe der Verschlüsselung besteht darin, das Paßwort für einen Betrachter der Datei \BIN\PASSWD derart zu „verstümmeln“, daß man es daraus nicht ableiten kann. Betrachtet man die Datei\BIN\PASSWD (siehe Kommando MKDIR), läßt sich sagen, daß die „Verstümmelung“ mit der Funktion crypt, also mit dem Data Encryption Standard (DES), ganz gut gelingt.

Implementierung
Die Implementierung des Kommandos PASSWD ist in Listing 3.10 abgedruckt. Die zentrale Funktion ist hier passwd (Zeilen 41-99). Innerhalb von passwd werden folgende Aufgaben erledigt:

Name
LOGIN - Einloggen in das System

Anwendung
LOGIN

Beschreibung
Das Kommando LOGIN dient zum Einloggen in das System. Es wird einmal gestartet und durchläuft daraufhin eine Endlosschleife, die immer wieder einen Benutzernamen und ein Paßwort einliest und daraufhin den Zugang zum System ermöglicht oder auch nicht. LOGIN startet dabei jeweils die in \BIN\PASSWD für einen Benutzer eingetragene Shell.

Implementierung
Die Implementierung des Kommandos LOGIN (Listing 3.11) umfaßt im wesentlichen drei Aufgaben:

Diese drei Aufgaben sind innerhalb der Funktion login zusammengefaßt, login wird ihrerseits innerhalb von main von einer Endlosschleife umrahmt.

Schlußbemerkung
Mit den heute vorgestellten Kommandos ist die Implementierung der Programmer ’ s Toolbox abgeschlossen. An dieser Stelle möchte ich allen Lesern für Ihr Interesse danken.


/*
 * Listing 3.8, Datei : mkuser c
 * Programm           : MKUSER - Erzeugen eines
 *                      Benutzerdatensatzes
 * Modifikationsdatum : 27-Dez-90
 * Abhängigkeiten     : stdio.h, local.h, usermain.h
 */

#include <stdio.h> 
#include "local.h" 
#include "usermain.h"

/*
 * Funktion : DEFAULT_SHELL
 *
 * Aufgabe  :
 *
 * Festlegung der Standardshell.
 */

#define DEFAULT_SHELL "\\BIN\\SSH.TTP"

/*
 * Funktion     : mkuser
 *
 * Parameter    : ok = mkuser(arge, argv),
 *                BOOLEAN ok;
 *                short argc;
 *                char *argv[];
 *
 * Aufgabe      :
 *
 * Interpretation der durch <argc> und <argv>
 * spezifizierten Parameterliste gemäß den Fest-
 * legungen des Kommandos MKUSER 
 */

BOOLEAN mkuser(argc, argv) 
short argc; 
char *argv[];
{   short i;

    if (argc == 2 || argc == 3) { 
        load_user_data(); 
        if (argc == 2)
            insert_replace_user(argv[1], "ohne", DEFAULT_SHELL);
        else
            insert_replace_user(argv[1], "ohne", argv[2]);

        save_user_data();
    }
    else {
        fprintf(stderr,"SYNOPSIS: mkuser user [ shell ]\n"); 
        return(FALSE);
    }
    return(TRUE);
}

void main(argc, argv) 
short argc; 
char *argv[],
{   if (!mkuser(argc, argv)) 
        exit(1); 
    exit(0);
}
/*
 * Listing 3.9, Datei : rmuser.c
 * Programm           : RMUSER - Löschen eines
 *                      Benutzerdatensatzes
 * Modifikationsdatum : 27-Dez-90
 * Abhängigkeiten     : stdio h, local.h, usermain.h
 */

#include <stdio.h>
#include "local.h"
#include "usermain.h"

/*
 * Funktion     : rmuser
 *
 * Parameter    : ok = rmuser(argc, argv);
 *                BOOLEAN ok;
 *                short argc;
 *                char *argv[];
 *
 * Aufgabe      :
 *
 * Interpretation der durch <argc> und <argv>
 * spezifizierten Parameterliste gemäß den Fest-
 * legungen des Kommandos RMUSER */

BOOLEAN rmuser(argc, argv) 
short argc; 
char *argv[];
{   short i;

    if (argc == 2) {
        load_user_data(); 
        delete_user(argv[1]); 
        save_user_data();
    }
    else {
        fprintf(stderr,"SYNOPSIS: rmuser user\n");
        return(FALSE);
    }
    return(TRUE);
}

void main(argc, argv) 
short argc; 
char *argv[];
{   if (!rmuser(argc, argv)) 
        exit(1); 
    exit(0);
}
/*
 * Listing 3.10, Datei : passwd.c
 * Programm            : PASSWD - Ändern von
 *                       Paßwörtern
 * Modifikationsdatum  : 27-Dez-90
 * Abhängigkeiten      : stdio.h, osbind.h, local.h,
 *                       usermain.h, crypt.h 
 */

#include <stdio.h>
#include <osbind.h>
#include "local.h"
#include "usermain.h"
#include "crypt.h"

/*
 * Funktion         : passwd
 *
 * Parameter        : ok = passwd(argc, argv);
 *                    BOOLEAN passwd;
 *                    short argc;
 *                    char *argv[];
 *
 * Aufgabe          :
 *
 * Interpretation der durch <argc> und <argv>
 * spezifizierten Parameterliste gemäß den Fest-
 * legungen des Kommandos PASSWD 
 */

#define MAXSTR 100

static char random_char()
{   unsigned char c;

    c = rand(); 
    c = c % 94 + 33; 
    return(c);
}

BOOLEAN passwd(argc, argv) 
short argc; 
char *argv[];
{   USER_LIST list;
    char      oldpasswdl[MAXSTR],
              oldpasswd2[MAXSTR], 
              newpasswd1[MAXSTR], 
              newpasswd2[MAXSTR], 
              salt[3],
              *erg;

    if (argc == 2) {
        load_user_data();
        list = find_user(argv[1]);
        input("old password?", oldpasswd1, FALSE);
        input("retype old password!", oldpasswd2, FALSE);
        if (strcmp(oldpasswd1, oldpasswd2) != 0)
        {
            printf("old passwords are different\n"); 
            return(FALSE);
        }
        input("new password?", newpasswd1, FALSE);
        input("retype new password!", newpasswd2, FALSE);
        if (strcmp(newpasswd1, newpasswd2) != 0)
        {
            printf("new passwords are different\n"); 
            return(FALSE);
        }
        if (list != NULL) {
            if (strcmp(list->passwd, "ohne") == 0 ||
                strcmp(list->passwd, crypt(oldpasswd1, list->passwd)) == 0) { 
                    srand(Gettime()); 
                    salt[0] = random_char(); 
                    salt[1] = random_char(); 
                    salt[2] = 0;
                    erg = crypt(newpasswd1, salt); 
                    free(list->passwd); 
                    list->passwd = malloc(strlen(erg)+ 1);
                    strcpy(list->passwd, erg); 
                    set_modification_bit();
                }
            else
                printf("incorrect old password\n");
        }
        else {
            crypt("Mit irgendwas", "ausbremsen"); 
            printf("unknown user\n");
        }
        save_user_data();
    }
    else {
        fprintf(stderr, "SYNOPSIS: passwd user\n");
        return(FALSE);
    }
    return(TRUE);
}

void main(argc, argv) 
short argc; 
char *argv[];
{   if(!passwd(argc, argv)) 
        exit(1); 
    exit(0);
}
/*
 * Listing 3.11, Datei : login.c
 * Programm            : LOGIN - Einloggen in das
 *                       System
 * Modifikationsdatum  : 6-Jan-90
 * Abhängigkeiten      : stdio.h, osbind.h, local.h, 
 *                       usermain.h, crypt.h
 */

#include <stdio.h>
#include <osbind.h>
#include "local.h"
#include "usermain.h"
#include "crypt.h"

/*
 * Funktion : login
 *
 * Parameter            : login(argc, argv);
 *                        short argc;
 *                        char *argv[];
 *
 * Aufgabe              :
 *
 * Interpretation der durch <argc> und <argv>
 * spezifizierten Parameterliste gemäß den Fest-
 * legungen des Kommandos LOGIN.
 */

#define MAXSTR 100

void login(argc, argv) 
short argc; 
char  *argv[];
{   USER_LIST list;
    char user[MAXSTR], passwd[MAXSTR], pdummy[MAXSTR];

    if (argc == 1) {
        input("login, user, TRUE); 
        input("password:", passwd, FALSE); 
        load_user_data(); 
        list = find_user(user); 
        if (list != NULL) {
            if ((strcmp(list->passwd, "ohne")
                && strcmp(passwd, "ohne”) == 0)
                || (strcmp(list->passwd, crypt(passwd, list->passwd)) == 0)) {
                
                /* login correct => shell starten */
                pdummy[0] = 0;
                Pexec(0, list->shell, pdummy, "");
            }
            else
                printf("login incorrect\n");
        }
        else {
            crypt("Mit irgendwas", "ausbremsen"); 
            printf("login incorrect\n");
        }
    }
    else {
        fprintf(stderr, "SYNOPSIS login\n"); 
        return;
    }
    return;
}

void main(argc, argv) 
short argc; 
char  *argv[];
{   do (
        login(argc, argv);
    }
    while(TRUE);
}

Dirk Brockhaus
Aus: ST-Computer 10 / 1991, Seite 146

Links

Copyright-Bestimmungen: siehe Über diese Seite