pure-pw.c

来自「功能强大的ftp服务器源代码」· C语言 代码 · 共 1,575 行 · 第 1/4 页

C
1,575
字号
#include <config.h>#include "ftpd.h"#include "pure-pw.h"#include "../puredb/src/puredb_write.h"#ifdef HAVE_POSIX_TERMIOS# include <termios.h>#elif defined(HAVE_TERMIO_H)# include <termio.h>#elif defined(HAVE_SGTTY_H)# include <sgtty.h>#endif#ifndef HAVE_GETOPT_LONG# include "bsd-getopt_long.h"#else# include <getopt.h>#endif#ifdef WITH_DMALLOC# include <dmalloc.h>#endif#ifdef PROBE_RANDOM_AT_RUNTIMEstatic const char *random_device;#endifstatic void disable_echo(void){    if (!isatty(0)) {        return;    }#ifdef ECHO# ifdef HAVE_POSIX_TERMIOS    {            struct termios p;                if (tcgetattr(0, &p) != 0) {            return;        }        p.c_lflag &= ~ECHO;#  ifndef TCSAFLUSH#   define TCSAFLUSH 0#  endif        tcsetattr(0, TCSAFLUSH, &p);    }# elif defined(HAVE_TERMIO_H) && defined(TCGETA)    {        struct termio tty;                if (ioctl(0, TCGETA, &tty) != 0) {            return;        }        tty.c_lflag &= ~ECHO;        ioctl(0, TCSETA, &tty);    }# else    {        struct sgttyb tty;                if (ioctl(0, TIOCGETP, &tty) != 0) {            return;        }        tty.sg_flags &= ~ECHO;        ioctl(0, TIOCSETN, &tty);    }# endif#endif}static void enable_echo(void){    if (!isatty(0)) {        return;    }    #ifdef ECHO# ifdef HAVE_POSIX_TERMIOS    {        struct termios p;                if (tcgetattr(0, &p) != 0) {            return;        }        p.c_lflag |= ECHO;#  ifndef TCSAFLUSH#   define TCSAFLUSH 0#  endif        tcsetattr(0, TCSAFLUSH, &p);    }# elif defined(HAVE_TERMIO_H) && defined(TCGETA)    {        struct termio tty;                if (ioctl(0, TCGETA, &tty) != 0) {            return;        }        tty.c_lflag |= ECHO;        ioctl(0, TCSETA, &tty);    }# else    {        struct sgttyb tty;                if (ioctl(0, TIOCGETP, &tty) != 0) {            return;        }        tty.sg_flags |= ECHO;        ioctl(0, TIOCSETN, &tty);    }# endif#endif}/* * The difference between this strtok() and the libc's one is that * this one doesn't skip empty fields, and takes a char instead of a * string as a delimiter. * This strtok2() variant leaves zeroes. */static char *my_strtok2(char *str, const char delim){    static char *s;    static char save;        if (str != NULL) {        if (*str == 0) {            return NULL;        }                s = str;        scan:        while (*s != 0 && *s != delim) {            s++;        }        save = *s;        *s = 0;                return str;    }    if (s == NULL || save == 0) {                return NULL;    }    s++;    str = s;        goto scan;}static void filter_pw_line_sep(char *str){    if (str == NULL) {        return;    }    while (*str != 0) {        if (*str == *PW_LINE_SEP) {            *str = '_';        }        str++;    }}static void help(void){    puts("\nUsage :\n\n"         "pure-pw useradd <login> [-f <passwd file>] -u <uid> [-g <gid>]\n"         "                -D/-d <home directory> [-c <gecos>]\n"         "                [-t <download bandwidth>] [-T <upload bandwidth>]\n"         "                [-n <max number of files>] [-N <max Mbytes>]\n"         "                [-q <upload ratio>] [-Q <download ratio>]\n"         "                [-r <allow client ip>/<mask>] [-R <deny client ip>/<mask>]\n"         "                [-i <allow local ip>/<mask>] [-I <deny local ip>/<mask>]\n"	 "                [-y <max number of concurrent sessions>]\n"         "                [-z <hhmm>-<hhmm>] [-m]\n"         "\n"         "pure-pw usermod <login> -f <passwd file> -u <uid> [-g <gid>]\n"         "                -D/-d <home directory> -[c <gecos>]\n"         "                [-t <download bandwidth>] [-T <upload bandwidth>]\n"         "                [-n <max number of files>] [-N <max Mbytes>]\n"         "                [-q <upload ratio>] [-Q <download ratio>]\n"         "                [-r <allow client ip>/<mask>] [-R <deny client ip>/<mask>]\n"         "                [-i <allow local ip>/<mask>] [-I <deny local ip>/<mask>]\n"	 "                [-y <max number of concurrent sessions>]\n"	          "                [-z <hhmm>-<hhmm>] [-m]\n"         "\n"         "pure-pw userdel <login> [-f <passwd file>] [-m]\n"         "\n"         "pure-pw passwd  <login> [-f <passwd file>] [-m]\n"         "\n"         "pure-pw show    <login> [-f <passwd file>]\n"         "\n"         "pure-pw mkdb    [<puredb database file> [-f <passwd file>]]\n"         "\n"         "pure-pw list    [-f <passwd file>]\n"         "\n"         "-d <home directory> : chroot user (recommended)\n"         "-D <home directory> : don't chroot user\n"	 "-<option> '' : set this option to unlimited\n"         "-m : also update the " DEFAULT_PW_DB " database\n"         "For a 1:10 ratio, use -q 1 -Q 10\n"         "To allow access only between 9 am and 6 pm, use -z 0900-1800\n"         "\n");#ifndef WITH_PUREDB    puts("*WARNING* : that pure-ftpd server hasn't been compiled with puredb support\n");#endif    exit(EXIT_SUCCESS);   }static void no_mem(void){    fprintf(stderr, "Out of memory : [%s]\n", strerror(errno));    exit(EXIT_FAILURE);}#ifdef PROBE_RANDOM_AT_RUNTIMEstatic void pw_zrand_probe(void){    static const char * const devices[] = {        "/dev/arandom", "/dev/urandom", "/dev/random", NULL    };    register const char * const *device = devices;        do {        if (access(*device, F_OK | R_OK) == 0) {            random_device = *device;            break;        }        device++;    } while (*device != NULL);}#endifstatic unsigned int pw_zrand(void){    int fd;    int ret;        if (#ifdef PROBE_RANDOM_AT_RUNTIME        ((fd = open(random_device, O_RDONLY | O_NONBLOCK)) == -1)#elif defined(HAVE_DEV_ARANDOM)        ((fd = open("/dev/arandom", O_RDONLY | O_NONBLOCK)) == -1)#elif defined(HAVE_DEV_URANDOM)        ((fd = open("/dev/urandom", O_RDONLY | O_NONBLOCK)) == -1)#else        ((fd = open("/dev/random", O_RDONLY | O_NONBLOCK)) == -1)#endif                ) {        nax:#ifdef HAVE_RANDOM        return (unsigned int) random();        #else        return (unsigned int) rand();#endif    }    if (read(fd, &ret, sizeof ret) != (ssize_t) sizeof ret) {        close(fd);        goto nax;    }    close(fd);            return (unsigned int) ret;}static char *best_crypt(const char * const pwd){    static const char crcars[64] =        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";    register const char *crypted;        if ((crypted = (const char *)      /* Blowfish */         crypt("test", "$2a$07$1234567890123456789012")) != NULL &&                strcmp(crypted, "$2a$07$123456789012345678901uKO4"               "/IReKqBzRzT6YaajGvw20UBdHW7m") == 0) {        char salt[] = "$2a$07$0000000000000000000000";                int c = 28;                do {                        c--;            salt[c] = crcars[pw_zrand() & 63];        } while (c > 7);                return (char *) crypt(pwd, salt);            } else if ((crypted = (const char *)    /* MD5 */                crypt("test", "$1$12345678$")) != NULL &&               strcmp(crypted, "$1$12345678$oEitTZYQtRHfNGmsFvTBA/") == 0) {        char salt[] = "$1$00000000";        int c = 10;                do {                        c--;            salt[c] = crcars[pw_zrand() & 63];        } while (c > 3);                return (char *) crypt(pwd, salt);    } else if ((crypted = (const char *)    /* Extended DES */                crypt("test", "_.../1234")) != NULL &&               strcmp(crypted, "_.../1234PAPUVmqGzpU") == 0) {        char salt[] = "_.../0000";        int c = 8;                do {            c--;            salt[c] = crcars[pw_zrand() & 63];        } while (c > 5);                return (char *) crypt(pwd, salt);    }    /* Simple DES */    {        char salt[] = "00";                salt[0] = crcars[pw_zrand() & 63];        salt[1] = crcars[pw_zrand() & 63];                return (char *) crypt(pwd, salt);            }    }char *newpasswd_filename(const char * const file){    size_t sizeof_file2;    char *file2;        sizeof_file2 = strlen(file) + sizeof NEWPASSWD_SUFFIX;    if ((file2 = malloc(sizeof_file2)) == NULL) {        return NULL;    }    (void) snprintf(file2, sizeof_file2, "%s%s", file, NEWPASSWD_SUFFIX);        return file2;}static void strip_lf(char *str){    char *f;        if (str == NULL) {        return;    }    if ((f = strchr(str, '\r')) != NULL) {        *f = 0;    }        if ((f = strchr(str, '\n')) != NULL) {        *f = 0;    }}static int parse_pw_line(char *line, PWInfo * const pwinfo){    pwinfo->login = NULL;    pwinfo->pwd = NULL;    pwinfo->gecos = NULL;    pwinfo->home = NULL;    pwinfo->allow_local_ip = pwinfo->deny_local_ip = NULL;    pwinfo->allow_client_ip = pwinfo->deny_client_ip = NULL;        pwinfo->has_bw_dl = 0;    pwinfo->has_bw_ul = 0;    pwinfo->has_quota_files = 0;    pwinfo->has_quota_size = 0;    pwinfo->has_ul_ratio = 0;    pwinfo->has_dl_ratio = 0;    pwinfo->has_time = 0;    pwinfo->time_begin = pwinfo->time_end = 0U;    pwinfo->uid = (uid_t) 0;    pwinfo->gid = (gid_t) 0;    pwinfo->has_per_user_max = 0;    pwinfo->per_user_max = 0U;        if ((line = my_strtok2(line, *PW_LINE_SEP)) == NULL || *line == 0) {   /* account */        return -1;    }    pwinfo->login = line;    if ((line = my_strtok2(NULL, *PW_LINE_SEP)) == NULL || *line == 0) {   /* pwd */        return -1;    }    pwinfo->pwd = line;    if ((line = my_strtok2(NULL, *PW_LINE_SEP)) == NULL || *line == 0) {   /* uid */        return -1;    }    pwinfo->uid = (uid_t) strtoul(line, NULL, 10);    if ((line = my_strtok2(NULL, *PW_LINE_SEP)) == NULL || *line == 0) {   /* gid */        return -1;    }    pwinfo->gid = (gid_t) strtoul(line, NULL, 10);    if (pwinfo->uid <= (uid_t) 0 || pwinfo->gid <= (gid_t) 0) {        return -1;    }    if ((line = my_strtok2(NULL, *PW_LINE_SEP)) == NULL) {   /* gecos */        return -1;    }    pwinfo->gecos = line;    if ((line = my_strtok2(NULL, *PW_LINE_SEP)) == NULL || *line == 0) {   /* home */        return -1;    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?