"Fossies" - the Fresh Open Source Software Archive

Member "passwdqc-2.0.3/passwdqc_parse.c" (23 Jun 2023, 5456 Bytes) of package /linux/privat/passwdqc-2.0.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "passwdqc_parse.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.0.0_vs_2.0.1.

    1 /*
    2  * Copyright (c) 2000-2003,2005,2016,2020,2021 by Solar Designer
    3  * Copyright (c) 2008,2009 by Dmitry V. Levin
    4  * See LICENSE
    5  */
    6 
    7 #ifdef _MSC_VER
    8 #define _CRT_NONSTDC_NO_WARNINGS /* we use POSIX function names */
    9 #endif
   10 
   11 #include <stdio.h>
   12 #include <stdlib.h>
   13 #include <string.h>
   14 #include <limits.h>
   15 
   16 #include "passwdqc.h"
   17 #include "concat.h"
   18 
   19 static const char *skip_prefix(const char *sample, const char *prefix)
   20 {
   21     size_t len = strlen(prefix);
   22 
   23     if (strncmp(sample, prefix, len))
   24         return NULL;
   25     return sample + len;
   26 }
   27 
   28 static int
   29 parse_option(passwdqc_params_t *params, char **reason, const char *option)
   30 {
   31     const char *err = "Invalid parameter value";
   32     const char * const err_oom = "Out of memory";
   33     const char *p;
   34     char *e;
   35     int i, rc = 0;
   36     unsigned long v;
   37 
   38     *reason = NULL;
   39     if ((p = skip_prefix(option, "min="))) {
   40         for (i = 0; i < 5; i++) {
   41             if (!strncmp(p, "disabled", 8)) {
   42                 v = INT_MAX;
   43                 p += 8;
   44             } else {
   45                 v = strtoul(p, &e, 10);
   46                 p = e;
   47             }
   48             if (i < 4 && *p++ != ',')
   49                 goto parse_error;
   50             if (v > INT_MAX)
   51                 goto parse_error;
   52             if (i && (int)v > params->qc.min[i - 1])
   53                 goto parse_error;
   54             params->qc.min[i] = v;
   55         }
   56         if (*p)
   57             goto parse_error;
   58     } else if ((p = skip_prefix(option, "max="))) {
   59         v = strtoul(p, &e, 10);
   60         if (*e || v < 8 || v > INT_MAX)
   61             goto parse_error;
   62         if (v > 10000)
   63             v = 10000;
   64         params->qc.max = v;
   65     } else if ((p = skip_prefix(option, "passphrase="))) {
   66         v = strtoul(p, &e, 10);
   67         if (*e || v > INT_MAX)
   68             goto parse_error;
   69         params->qc.passphrase_words = v;
   70     } else if ((p = skip_prefix(option, "match="))) {
   71         v = strtoul(p, &e, 10);
   72         if (*e || v > INT_MAX)
   73             goto parse_error;
   74         params->qc.match_length = v;
   75     } else if ((p = skip_prefix(option, "similar="))) {
   76         if (!strcmp(p, "permit"))
   77             params->qc.similar_deny = 0;
   78         else if (!strcmp(p, "deny"))
   79             params->qc.similar_deny = 1;
   80         else
   81             goto parse_error;
   82     } else if ((p = skip_prefix(option, "random="))) {
   83         v = strtoul(p, &e, 10);
   84         if (!strcmp(e, ",only")) {
   85             e += 5;
   86             params->qc.min[4] = INT_MAX;
   87         }
   88         if (*e || (v && v < 24) || v > 136)
   89             goto parse_error;
   90         params->qc.random_bits = v;
   91     } else if ((p = skip_prefix(option, "wordlist="))) {
   92         free(params->qc.wordlist);
   93         params->qc.wordlist = NULL;
   94         if (*p && !(params->qc.wordlist = strdup(p))) {
   95             err = err_oom;
   96             goto parse_error;
   97         }
   98     } else if ((p = skip_prefix(option, "denylist="))) {
   99         free(params->qc.denylist);
  100         params->qc.denylist = NULL;
  101         if (*p && !(params->qc.denylist = strdup(p))) {
  102             err = err_oom;
  103             goto parse_error;
  104         }
  105     } else if ((p = skip_prefix(option, "filter="))) {
  106         free(params->qc.filter);
  107         params->qc.filter = NULL;
  108         if (*p && !(params->qc.filter = strdup(p))) {
  109             err = err_oom;
  110             goto parse_error;
  111         }
  112     } else if ((p = skip_prefix(option, "enforce="))) {
  113         params->pam.flags &= ~F_ENFORCE_MASK;
  114         if (!strcmp(p, "users"))
  115             params->pam.flags |= F_ENFORCE_USERS;
  116         else if (!strcmp(p, "everyone"))
  117             params->pam.flags |= F_ENFORCE_EVERYONE;
  118         else if (strcmp(p, "none"))
  119             goto parse_error;
  120     } else if (!strcmp(option, "non-unix")) {
  121         if (params->pam.flags & F_CHECK_OLDAUTHTOK)
  122             goto parse_error;
  123         params->pam.flags |= F_NON_UNIX;
  124     } else if ((p = skip_prefix(option, "retry="))) {
  125         v = strtoul(p, &e, 10);
  126         if (*e || v > INT_MAX)
  127             goto parse_error;
  128         params->pam.retry = v;
  129     } else if ((p = skip_prefix(option, "ask_oldauthtok"))) {
  130         params->pam.flags &= ~F_ASK_OLDAUTHTOK_MASK;
  131         if (params->pam.flags & F_USE_FIRST_PASS)
  132             goto parse_error;
  133         if (!p[0])
  134             params->pam.flags |= F_ASK_OLDAUTHTOK_PRELIM;
  135         else if (!strcmp(p, "=update"))
  136             params->pam.flags |= F_ASK_OLDAUTHTOK_UPDATE;
  137         else
  138             goto parse_error;
  139     } else if (!strcmp(option, "check_oldauthtok")) {
  140         if (params->pam.flags & F_NON_UNIX)
  141             goto parse_error;
  142         params->pam.flags |= F_CHECK_OLDAUTHTOK;
  143     } else if (!strcmp(option, "use_first_pass")) {
  144         if (params->pam.flags & F_ASK_OLDAUTHTOK_MASK)
  145             goto parse_error;
  146         params->pam.flags |= F_USE_FIRST_PASS | F_USE_AUTHTOK;
  147     } else if (!strcmp(option, "use_authtok")) {
  148         params->pam.flags |= F_USE_AUTHTOK;
  149     } else if (!strcmp(option, "noaudit")) {
  150         params->pam.flags |= F_NO_AUDIT;
  151     } else if ((p = skip_prefix(option, "config="))) {
  152         if ((rc = passwdqc_params_load(params, reason, p)))
  153             goto parse_error;
  154     } else {
  155         err = "Invalid parameter";
  156         goto parse_error;
  157     }
  158 
  159     return 0;
  160 
  161 parse_error:
  162     passwdqc_params_free(params);
  163     e = concat("Error parsing parameter \"", option, "\": ",
  164         (rc ? (*reason ? *reason : err_oom) : err), NULL);
  165     free(*reason);
  166     *reason = e;
  167     return rc ? rc : -1;
  168 }
  169 
  170 int
  171 passwdqc_params_parse(passwdqc_params_t *params, char **reason,
  172     int argc, const char *const *argv)
  173 {
  174     int i;
  175 
  176     *reason = NULL;
  177     for (i = 0; i < argc; ++i) {
  178         int rc;
  179 
  180         if ((rc = parse_option(params, reason, argv[i])))
  181             return rc;
  182     }
  183     return 0;
  184 }
  185 
  186 static const passwdqc_params_t defaults = {
  187     {
  188         {INT_MAX, 24, 11, 8, 7},    /* min */
  189         72,             /* max */
  190         3,              /* passphrase_words */
  191         4,              /* match_length */
  192         1,              /* similar_deny */
  193         47,             /* random_bits */
  194         NULL,               /* wordlist */
  195         NULL,               /* denylist */
  196         NULL                /* filter */
  197     },
  198     {
  199         F_ENFORCE_EVERYONE,     /* flags */
  200         3               /* retry */
  201     }
  202 };
  203 
  204 void passwdqc_params_reset(passwdqc_params_t *params)
  205 {
  206     *params = defaults;
  207 }
  208 
  209 void passwdqc_params_free(passwdqc_params_t *params)
  210 {
  211     free(params->qc.wordlist);
  212     free(params->qc.denylist);
  213     free(params->qc.filter);
  214     passwdqc_params_reset(params);
  215 }