Changeset 547 in openpam


Ignore:
Timestamp:
Apr 1, 2012, 3:01:21 PM (3 years ago)
Author:
des
Message:

Add an openpam_straddch() function that appends a character to a
string, reallocating the string if necessary.

Add an openpam_readword() function that reads a single word from a
file according to the usual shell quoting rules.

Add an openpam_readlinev() function that uses openpam_readword() to
read an entire line and return a list of the words it contained.

Rewrite openpam_parse_chain() using openpam_readlinev(), which greatly
simplifies the code and ensures correct parsing of module option.

Thanks to Maëlle Lesage for pointing out the issue and writing an
early version of what became the main loop in openpam_readword().

Location:
trunk
Files:
3 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/CREDITS

    r526 r547  
    2828        Juli Mallett <jmallett@freebsd.org> 
    2929        Jörg Sonnenberger <joerg@britannica.bec.de> 
     30        Maëlle Lesage <lesage.maelle@gmail.com> 
    3031        Mark Murray <markm@freebsd.org> 
    3132        Matthias Drochner <drochner@netbsd.org> 
  • trunk/doc/man

    • Property svn:ignore
      •  

        old new  
        99openpam_nullconv.3 
        1010openpam_readline.3 
         11openpam_readlinev.3 
         12openpam_readword.3 
        1113openpam_restore_cred.3 
        1214openpam_set_option.3 
         15openpam_straddch.3 
        1316openpam_subst.3 
        1417openpam_ttyconv.3 
  • trunk/doc/man/Makefile.am

    r535 r547  
    4343        openpam_nullconv.3 \ 
    4444        openpam_readline.3 \ 
     45        openpam_readlinev.3 \ 
     46        openpam_readword.3 \ 
    4547        openpam_restore_cred.3 \ 
    4648        openpam_set_option.3 \ 
  • trunk/include/security/openpam.h

    r535 r547  
    159159        OPENPAM_NONNULL((1)); 
    160160 
     161char ** 
     162openpam_readlinev(FILE *_f, 
     163        int *_lineno, 
     164        int *_lenp) 
     165        OPENPAM_NONNULL((1)); 
     166 
     167char * 
     168openpam_readword(FILE *_f, 
     169        int *_lineno, 
     170        size_t *_lenp) 
     171        OPENPAM_NONNULL((1)); 
     172#endif 
     173 
    161174int 
    162175openpam_straddch(char **_str, 
    163     size_t *_sizep, 
    164     size_t *_lenp, 
    165     int ch); 
    166 #endif 
     176        size_t *_sizep, 
     177        size_t *_lenp, 
     178        int ch) 
     179        OPENPAM_NONNULL((1)); 
    167180 
    168181/* 
  • trunk/lib/Makefile.am

    r528 r547  
    2929        openpam_nullconv.c \ 
    3030        openpam_readline.c \ 
     31        openpam_readlinev.c \ 
     32        openpam_readword.c \ 
    3133        openpam_restore_cred.c \ 
    3234        openpam_set_option.c \ 
  • trunk/lib/openpam_configure.c

    r524 r547  
    11/*- 
    22 * Copyright (c) 2001-2003 Networks Associates Technology, Inc. 
    3  * Copyright (c) 2004-2011 Dag-Erling Smørgrav 
     3 * Copyright (c) 2004-2012 Dag-Erling Smørgrav 
    44 * All rights reserved. 
    55 * 
     
    5151 
    5252#include "openpam_impl.h" 
     53#include "openpam_ctype.h" 
    5354#include "openpam_strlcmp.h" 
    5455 
     
    5657 
    5758/* 
    58  * Evaluates to non-zero if the argument is a linear whitespace character. 
    59  */ 
    60 #define is_lws(ch)                              \ 
    61         (ch == ' ' || ch == '\t') 
    62  
    63 /* 
    64  * Evaluates to non-zero if the argument is a printable ASCII character. 
    65  * Assumes that the execution character set is a superset of ASCII. 
    66  */ 
    67 #define is_p(ch) \ 
    68         (ch >= '!' && ch <= '~') 
    69  
    70 /* 
    71  * Returns non-zero if the argument belongs to the POSIX Portable Filename 
    72  * Character Set.  Assumes that the execution character set is a superset 
    73  * of ASCII. 
    74  */ 
    75 #define is_pfcs(ch)                             \ 
    76         ((ch >= '0' && ch <= '9') ||            \ 
    77          (ch >= 'A' && ch <= 'Z') ||            \ 
    78          (ch >= 'a' && ch <= 'z') ||            \ 
    79          ch == '.' || ch == '_' || ch == '-') 
    80  
    81 /* 
    82  * Parse the service name. 
    83  * 
    84  * Returns the length of the service name, or 0 if the end of the string 
    85  * was reached or a disallowed non-whitespace character was encountered. 
    86  * 
    87  * If parse_service_name() is successful, it updates *service to point to 
    88  * the first character of the service name and *line to point one 
    89  * character past the end.  If it reaches the end of the string, it 
    90  * updates *line to point to the terminating NUL character and leaves 
    91  * *service unmodified.  In all other cases, it leaves both *line and 
    92  * *service unmodified. 
    93  * 
    94  * Allowed characters are all characters in the POSIX portable filename 
    95  * character set. 
     59 * Validate a service name. 
     60 * 
     61 * Returns a non-zero value if the argument points to a NUL-terminated 
     62 * string consisting entirely of characters in the POSIX portable filename 
     63 * character set, excluding the path separator character. 
    9664 */ 
    9765static int 
    98 parse_service_name(char **line, char **service) 
    99 { 
    100         char *b, *e; 
    101  
    102         for (b = *line; *b && is_lws(*b); ++b) 
    103                 /* nothing */ ; 
    104         if (!*b) { 
    105                 *line = b; 
    106                 return (0); 
    107         } 
    108         for (e = b; *e && !is_lws(*e); ++e) 
    109                 if (!is_pfcs(*e)) 
     66valid_service_name(const char *name) 
     67{ 
     68        const char *p; 
     69 
     70        for (p = name; *p != '\0'; ++p) 
     71                if (!is_pfcs(*p)) 
    11072                        return (0); 
    111         if (e == b) 
    112                 return (0); 
    113         *line = e; 
    114         *service = b; 
    115         return (e - b); 
     73        return (1); 
    11674} 
    11775 
     
    11977 * Parse the facility name. 
    12078 * 
    121  * Returns the corresponding pam_facility_t value, or -1 if the end of the 
    122  * string was reached, a disallowed non-whitespace character was 
    123  * encountered, or the first word was not a recognized facility name. 
    124  * 
    125  * If parse_facility_name() is successful, it updates *line to point one 
    126  * character past the end of the facility name.  If it reaches the end of 
    127  * the string, it updates *line to point to the terminating NUL character. 
    128  * In all other cases, it leaves *line unmodified. 
     79 * Returns the corresponding pam_facility_t value, or -1 if the argument 
     80 * is not a valid facility name. 
    12981 */ 
    13082static pam_facility_t 
    131 parse_facility_name(char **line) 
    132 { 
    133         char *b, *e; 
     83parse_facility_name(const char *name) 
     84{ 
    13485        int i; 
    13586 
    136         for (b = *line; *b && is_lws(*b); ++b) 
    137                 /* nothing */ ; 
    138         if (!*b) { 
    139                 *line = b; 
    140                 return ((pam_facility_t)-1); 
    141         } 
    142         for (e = b; *e && !is_lws(*e); ++e) 
    143                 /* nothing */ ; 
    144         if (e == b) 
    145                 return ((pam_facility_t)-1); 
    14687        for (i = 0; i < PAM_NUM_FACILITIES; ++i) 
    147                 if (strlcmp(pam_facility_name[i], b, e - b) == 0) 
    148                         break; 
    149         if (i == PAM_NUM_FACILITIES) 
    150                 return ((pam_facility_t)-1); 
    151         *line = e; 
    152         return (i); 
    153 } 
    154  
    155 /* 
    156  * Parse the word "include". 
    157  * 
    158  * If the next word on the line is "include", parse_include() updates 
    159  * *line to point one character past "include" and returns 1.  Otherwise, 
    160  * it leaves *line unmodified and returns 0. 
     88                if (strcmp(pam_facility_name[i], name) == 0) 
     89                        return (i); 
     90        return ((pam_facility_t)-1); 
     91} 
     92 
     93/* 
     94 * Parse the control flag. 
     95 * 
     96 * Returns the corresponding pam_control_t value, or -1 if the argument is 
     97 * not a valid control flag name. 
     98 */ 
     99static pam_control_t 
     100parse_control_flag(const char *name) 
     101{ 
     102        int i; 
     103 
     104        for (i = 0; i < PAM_NUM_CONTROL_FLAGS; ++i) 
     105                if (strcmp(pam_control_flag_name[i], name) == 0) 
     106                        return (i); 
     107        return ((pam_control_t)-1); 
     108} 
     109 
     110/* 
     111 * Validate a file name. 
     112 * 
     113 * Returns a non-zero value if the argument points to a NUL-terminated 
     114 * string consisting entirely of characters in the POSIX portable filename 
     115 * character set, including the path separator character. 
    161116 */ 
    162117static int 
    163 parse_include(char **line) 
    164 { 
    165         char *b, *e; 
    166  
    167         for (b = *line; *b && is_lws(*b); ++b) 
    168                 /* nothing */ ; 
    169         if (!*b) { 
    170                 *line = b; 
    171                 return (-1); 
    172         } 
    173         for (e = b; *e && !is_lws(*e); ++e) 
    174                 /* nothing */ ; 
    175         if (e == b) 
    176                 return (0); 
    177         if (strlcmp("include", b, e - b) != 0) 
    178                 return (0); 
    179         *line = e; 
     118valid_filename(const char *name) 
     119{ 
     120        const char *p; 
     121 
     122        for (p = name; *p != '\0'; ++p) 
     123                if (!is_pfcs(*p) && *p != '/') 
     124                        return (0); 
    180125        return (1); 
    181 } 
    182  
    183 /* 
    184  * Parse the control flag. 
    185  * 
    186  * Returns the corresponding pam_control_t value, or -1 if the end of the 
    187  * string was reached, a disallowed non-whitespace character was 
    188  * encountered, or the first word was not a recognized control flag. 
    189  * 
    190  * If parse_control_flag() is successful, it updates *line to point one 
    191  * character past the end of the control flag.  If it reaches the end of 
    192  * the string, it updates *line to point to the terminating NUL character. 
    193  * In all other cases, it leaves *line unmodified. 
    194  */ 
    195 static pam_control_t 
    196 parse_control_flag(char **line) 
    197 { 
    198         char *b, *e; 
    199         int i; 
    200  
    201         for (b = *line; *b && is_lws(*b); ++b) 
    202                 /* nothing */ ; 
    203         if (!*b) { 
    204                 *line = b; 
    205                 return ((pam_control_t)-1); 
    206         } 
    207         for (e = b; *e && !is_lws(*e); ++e) 
    208                 /* nothing */ ; 
    209         if (e == b) 
    210                 return ((pam_control_t)-1); 
    211         for (i = 0; i < PAM_NUM_CONTROL_FLAGS; ++i) 
    212                 if (strlcmp(pam_control_flag_name[i], b, e - b) == 0) 
    213                         break; 
    214         if (i == PAM_NUM_CONTROL_FLAGS) 
    215                 return ((pam_control_t)-1); 
    216         *line = e; 
    217         return (i); 
    218 } 
    219  
    220 /* 
    221  * Parse a file name. 
    222  * 
    223  * Returns the length of the file name, or 0 if the end of the string was 
    224  * reached or a disallowed non-whitespace character was encountered. 
    225  * 
    226  * If parse_filename() is successful, it updates *filename to point to the 
    227  * first character of the filename and *line to point one character past 
    228  * the end.  If it reaches the end of the string, it updates *line to 
    229  * point to the terminating NUL character and leaves *filename unmodified. 
    230  * In all other cases, it leaves both *line and *filename unmodified. 
    231  * 
    232  * Allowed characters are all characters in the POSIX portable filename 
    233  * character set, plus the path separator (forward slash). 
    234  */ 
    235 static int 
    236 parse_filename(char **line, char **filename) 
    237 { 
    238         char *b, *e; 
    239  
    240         for (b = *line; *b && is_lws(*b); ++b) 
    241                 /* nothing */ ; 
    242         if (!*b) { 
    243                 *line = b; 
    244                 return (0); 
    245         } 
    246         for (e = b; *e && !is_lws(*e); ++e) 
    247                 if (!is_pfcs(*e) && *e != '/') 
    248                         return (0); 
    249         if (e == b) 
    250                 return (0); 
    251         *line = e; 
    252         *filename = b; 
    253         return (e - b); 
    254 } 
    255  
    256 /* 
    257  * Parse an option. 
    258  * 
    259  * Returns a dynamically allocated string containing the next module 
    260  * option, or NULL if the end of the string was reached or a disallowed 
    261  * non-whitespace character was encountered. 
    262  * 
    263  * If parse_option() is successful, it updates *line to point one 
    264  * character past the end of the option.  If it reaches the end of the 
    265  * string, it updates *line to point to the terminating NUL character.  In 
    266  * all other cases, it leaves *line unmodified. 
    267  * 
    268  * If parse_option() fails to allocate memory, it will return NULL and set 
    269  * errno to a non-zero value. 
    270  * 
    271  * Allowed characters for option names are all characters in the POSIX 
    272  * portable filename character set.  Allowed characters for option values 
    273  * are any printable non-whitespace characters.  The option value may be 
    274  * quoted in either single or double quotes, in which case space 
    275  * characters and whichever quote character was not used are allowed. 
    276  * Note that the entire value must be quoted, not just part of it. 
    277  */ 
    278 static char * 
    279 parse_option(char **line) 
    280 { 
    281         char *nb, *ne, *vb, *ve; 
    282         unsigned char q = 0; 
    283         char *option; 
    284         size_t size; 
    285  
    286         errno = 0; 
    287         for (nb = *line; *nb && is_lws(*nb); ++nb) 
    288                 /* nothing */ ; 
    289         if (!*nb) { 
    290                 *line = nb; 
    291                 return (NULL); 
    292         } 
    293         for (ne = nb; *ne && !is_lws(*ne) && *ne != '='; ++ne) 
    294                 if (!is_pfcs(*ne)) 
    295                         return (NULL); 
    296         if (ne == nb) 
    297                 return (NULL); 
    298         if (*ne == '=') { 
    299                 vb = ne + 1; 
    300                 if (*vb == '"' || *vb == '\'') 
    301                         q = *vb++; 
    302                 for (ve = vb; 
    303                      *ve && *ve != q && (is_p(*ve) || (q && is_lws(*ve))); 
    304                      ++ve) 
    305                         /* nothing */ ; 
    306                 if (q && *ve != q) 
    307                         /* non-printable character or missing endquote */ 
    308                         return (NULL); 
    309                 if (q && *(ve + 1) && !is_lws(*(ve + 1))) 
    310                         /* garbage after value */ 
    311                         return (NULL); 
    312         } else { 
    313                 vb = ve = ne; 
    314         } 
    315         size = (ne - nb) + 1; 
    316         if (ve > vb) 
    317                 size += (ve - vb) + 1; 
    318         if ((option = malloc(size)) == NULL) 
    319                 return (NULL); 
    320         strncpy(option, nb, ne - nb); 
    321         if (ve > vb) { 
    322                 option[ne - nb] = '='; 
    323                 strncpy(option + (ne - nb) + 1, vb, ve - vb); 
    324         } 
    325         option[size - 1] = '\0'; 
    326         *line = q ? ve + 1 : ve; 
    327         return (option); 
    328 } 
    329  
    330 /* 
    331  * Consume trailing whitespace. 
    332  * 
    333  * If there are no non-whitespace characters left on the line, parse_eol() 
    334  * updates *line to point at the terminating NUL character and returns 0. 
    335  * Otherwise, it leaves *line unmodified and returns a non-zero value. 
    336  */ 
    337 static int 
    338 parse_eol(char **line) 
    339 { 
    340         char *p; 
    341  
    342         for (p = *line; *p && is_lws(*p); ++p) 
    343                 /* nothing */ ; 
    344         if (*p) 
    345                 return ((unsigned char)*p); 
    346         *line = p; 
    347         return (0); 
    348126} 
    349127 
     
    368146        pam_facility_t fclt; 
    369147        pam_control_t ctlf; 
    370         char *line, *str, *name; 
    371         char *option, **optv; 
    372         int count, len, lineno, ret, serrno; 
     148        char *name, *servicename, *modulename; 
     149        int count, lineno, ret, serrno; 
     150        char **wordv, *word; 
     151        int i, wordc; 
    373152 
    374153        count = 0; 
     
    376155        name = NULL; 
    377156        lineno = 0; 
    378         while ((line = openpam_readline(f, &lineno, NULL)) != NULL) { 
    379                 /* get service name if necessary */ 
    380                 if (style == pam_conf_style) { 
    381                         if ((len = parse_service_name(&line, &str)) == 0) { 
    382                                 openpam_log(PAM_LOG_NOTICE, 
    383                                     "%s(%d): invalid service name (ignored)", 
    384                                     filename, lineno); 
    385                                 FREE(line); 
    386                                 continue; 
    387                         } 
    388                         if (strlcmp(service, str, len) != 0) { 
    389                                 FREE(line); 
    390                                 continue; 
    391                         } 
    392                 } 
    393  
    394                 /* get facility name */ 
    395                 if ((fclt = parse_facility_name(&line)) == (pam_facility_t)-1) { 
     157        wordc = 0; 
     158        wordv = NULL; 
     159        while ((wordv = openpam_readlinev(f, &lineno, &wordc)) != NULL) { 
     160                /* blank line? */ 
     161                if (wordc == 0) { 
     162                        FREEV(wordc, wordv); 
     163                        continue; 
     164                } 
     165                i = 0; 
     166 
     167                /* check service name if necessary */ 
     168                if (style == pam_conf_style && 
     169                    strcmp(wordv[i++], service) != 0) { 
     170                        FREEV(wordc, wordv); 
     171                        continue; 
     172                } 
     173 
     174                /* check facility name */ 
     175                if ((word = wordv[i++]) == NULL || 
     176                    (fclt = parse_facility_name(word)) == (pam_facility_t)-1) { 
    396177                        openpam_log(PAM_LOG_ERROR, 
    397178                            "%s(%d): missing or invalid facility", 
     
    400181                } 
    401182                if (facility != fclt && facility != PAM_FACILITY_ANY) { 
    402                         FREE(line); 
     183                        FREEV(wordc, wordv); 
    403184                        continue; 
    404185                } 
    405186 
    406187                /* check for "include" */ 
    407                 if (parse_include(&line)) { 
    408                         if ((len = parse_service_name(&line, &str)) == 0) { 
     188                if ((word = wordv[i++]) != NULL && 
     189                    strcmp(word, "include") == 0) { 
     190                        if ((servicename = wordv[i++]) == NULL || 
     191                            !valid_service_name(servicename)) { 
    409192                                openpam_log(PAM_LOG_ERROR, 
    410                                     "%s(%d): missing or invalid filename", 
     193                                    "%s(%d): missing or invalid service name", 
    411194                                    filename, lineno); 
    412195                                goto fail; 
    413196                        } 
    414                         if ((name = strndup(str, len)) == NULL) 
    415                                 goto syserr; 
    416                         if (parse_eol(&line) != 0) { 
     197                        if (wordv[i] != NULL) { 
    417198                                openpam_log(PAM_LOG_ERROR, 
    418199                                    "%s(%d): garbage at end of line", 
     
    420201                                goto fail; 
    421202                        } 
    422                         ret = openpam_load_chain(pamh, name, fclt); 
    423                         FREE(name); 
     203                        ret = openpam_load_chain(pamh, servicename, fclt); 
     204                        FREEV(wordc, wordv); 
    424205                        if (ret < 0) 
    425206                                goto fail; 
    426                         FREE(line); 
    427207                        continue; 
    428208                } 
    429209 
    430210                /* get control flag */ 
    431                 if ((ctlf = parse_control_flag(&line)) == (pam_control_t)-1) { 
     211                if (word == NULL || /* same word we compared to "include" */ 
     212                    (ctlf = parse_control_flag(word)) == (pam_control_t)-1) { 
    432213                        openpam_log(PAM_LOG_ERROR, 
    433214                            "%s(%d): missing or invalid control flag", 
     
    437218 
    438219                /* get module name */ 
    439                 if ((len = parse_filename(&line, &str)) == 0) { 
     220                if ((modulename = wordv[i++]) == NULL || 
     221                    !valid_filename(modulename)) { 
    440222                        openpam_log(PAM_LOG_ERROR, 
    441223                            "%s(%d): missing or invalid module name", 
     
    443225                        goto fail; 
    444226                } 
    445                 if ((name = strndup(str, len)) == NULL) 
    446                         goto syserr; 
    447227 
    448228                /* allocate new entry */ 
     
    451231                this->flag = ctlf; 
    452232 
    453                 /* get module options */ 
    454                 if ((this->optv = malloc(sizeof *optv)) == NULL) 
    455                         goto syserr; 
    456                 this->optc = 0; 
    457                 while ((option = parse_option(&line)) != NULL) { 
    458                         optv = realloc(this->optv, 
    459                             (this->optc + 2) * sizeof *optv); 
    460                         if (optv == NULL) 
    461                                 goto syserr; 
    462                         this->optv = optv; 
    463                         this->optv[this->optc++] = option; 
    464                 } 
    465                 this->optv[this->optc] = NULL; 
    466                 if (*line != '\0') { 
    467                         openpam_log(PAM_LOG_ERROR, 
    468                             "%s(%d): syntax error in module options", 
    469                             filename, lineno); 
     233                /* load module */ 
     234                if ((this->module = openpam_load_module(modulename)) == NULL) 
    470235                        goto fail; 
    471                 } 
    472  
    473                 /* load module */ 
    474                 this->module = openpam_load_module(name); 
    475                 FREE(name); 
    476                 if (this->module == NULL) 
    477                         goto fail; 
     236 
     237                /* 
     238                 * The remaining items in wordv are the module's 
     239                 * arguments.  We could set this->optv = wordv + i, but 
     240                 * then free(this->optv) wouldn't work.  Instead, we free 
     241                 * the words we've already consumed, shift the rest up, 
     242                 * and clear the tail end of the array. 
     243                 */ 
     244                this->optc = wordc - i; 
     245                for (i = 0; i < wordc - this->optc; ++i) { 
     246                        FREE(wordv[i]); 
     247                        wordv[i] = wordv[wordc - this->optc + i]; 
     248                        wordv[wordc - this->optc + i] = NULL; 
     249                } 
     250                this->optv = wordv; 
     251                wordv = NULL; 
     252                wordc = 0; 
    478253 
    479254                /* hook it up */ 
     
    484259                this = NULL; 
    485260                ++count; 
    486  
    487                 /* next please... */ 
    488                 FREE(line); 
    489261        } 
     262        /* 
     263         * The loop ended because openpam_readword() returned NULL, which 
     264         * can happen for four different reasons: an I/O error (ferror(f) 
     265         * is true), a memory allocation failure (ferror(f) is false, 
     266         * errno is non-zero) 
     267         */ 
     268        if (ferror(f) || errno != 0) 
     269                goto syserr; 
    490270        if (!feof(f)) 
    491                 goto syserr; 
     271                goto fail; 
    492272        fclose(f); 
    493273        return (count); 
     
    499279fail: 
    500280        serrno = errno; 
    501         if (this && this->optc) { 
    502                 while (this->optc--) 
    503                         FREE(this->optv[this->optc]); 
    504                 FREE(this->optv); 
    505         } 
     281        if (this && this->optc && this->optv) 
     282                FREEV(this->optc, this->optv); 
    506283        FREE(this); 
    507         FREE(line); 
     284        FREEV(wordc, wordv); 
     285        FREE(wordv); 
    508286        FREE(name); 
     287        fclose(f); 
    509288        errno = serrno; 
    510289        return (-1); 
     
    539318        int ret, serrno; 
    540319 
     320        if (!valid_service_name(service)) { 
     321                openpam_log(PAM_LOG_ERROR, "invalid service name"); 
     322                errno = EINVAL; 
     323                RETURNN(-1); 
     324        } 
    541325        ENTERS(facility < 0 ? "any" : pam_facility_name[facility]); 
    542326        for (path = openpam_policy_path; *path != NULL; ++path) { 
  • trunk/lib/openpam_impl.h

    r535 r547  
    158158pam_module_t    *openpam_dynamic(const char *); 
    159159 
    160 #define FREE(p) do { free((p)); (p) = NULL; } while (0) 
     160#define FREE(p)                                 \ 
     161        do {                                    \ 
     162                free(p);                        \ 
     163                (p) = NULL;                     \ 
     164        } while (0) 
     165 
     166#define FREEV(c, v)                             \ 
     167        do {                                    \ 
     168                while (c) {                     \ 
     169                        --(c);                  \ 
     170                        FREE((v)[(c)]);         \ 
     171                }                               \ 
     172                FREE(v);                        \ 
     173        } while (0) 
    161174 
    162175#include "openpam_constants.h" 
  • trunk/lib/openpam_load.c

    r491 r547  
    109109        openpam_destroy_chain(chain->next); 
    110110        chain->next = NULL; 
    111         while (chain->optc--) 
    112                 FREE(chain->optv[chain->optc]); 
    113         FREE(chain->optv); 
     111        FREEV(chain->optc, chain->optv); 
    114112        openpam_release_module(chain->module); 
    115113        chain->module = NULL; 
  • trunk/lib/openpam_readline.c

    r473 r547  
    4545 
    4646#include <security/pam_appl.h> 
     47 
    4748#include "openpam_impl.h" 
    4849 
     
    6263        int ch; 
    6364 
    64         if ((line = malloc(MIN_LINE_LENGTH)) == NULL) 
     65        if ((line = malloc(size = MIN_LINE_LENGTH)) == NULL) { 
     66                openpam_log(PAM_LOG_ERROR, "malloc(): %m"); 
    6567                return (NULL); 
    66         size = MIN_LINE_LENGTH; 
     68        } 
    6769        len = 0; 
    68  
    69 #define line_putch(ch) do { \ 
    70         if (len >= size - 1) { \ 
    71                 char *tmp = realloc(line, size *= 2); \ 
    72                 if (tmp == NULL) \ 
    73                         goto fail; \ 
    74                 line = tmp; \ 
    75         } \ 
    76         line[len++] = ch; \ 
    77         line[len] = '\0'; \ 
    78 } while (0) 
    79  
    8070        for (;;) { 
    8171                ch = fgetc(f); 
     
    10696                        break; 
    10797                } 
    108                 /* whitespace */ 
    109                 if (isspace(ch)) { 
    110                         /* ignore leading whitespace */ 
    111                         /* collapse linear whitespace */ 
    112                         if (len > 0 && line[len - 1] != ' ') 
    113                                 line_putch(' '); 
    114                         continue; 
    115                 } 
    11698                /* anything else */ 
    117                 line_putch(ch); 
     99                if (openpam_straddch(&line, &size, &len, ch) != 0) 
     100                        goto fail; 
    118101        } 
    119  
    120         /* remove trailing whitespace */ 
    121         while (len > 0 && isspace((unsigned char)line[len - 1])) 
    122                 --len; 
    123         line[len] = '\0'; 
    124102        if (len == 0) 
    125103                goto fail; 
    126104        if (lenp != NULL) 
    127105                *lenp = len; 
     106        openpam_log(PAM_LOG_LIBDEBUG, "returning '%s'", line); 
    128107        return (line); 
    129108fail: 
     
    134113/** 
    135114 * The =openpam_readline function reads a line from a file, and returns it 
    136  * in a NUL-terminated buffer allocated with =malloc. 
     115 * in a NUL-terminated buffer allocated with =!malloc. 
    137116 * 
    138117 * The =openpam_readline function performs a certain amount of processing 
    139118 * on the data it reads: 
    140119 * 
    141  *  - Comments (introduced by a hash sign) are stripped, as is leading and 
    142  *    trailing whitespace. 
    143  *  - Any amount of linear whitespace is collapsed to a single space. 
     120 *  - Comments (introduced by a hash sign) are stripped. 
     121 * 
    144122 *  - Blank lines are ignored. 
     123 * 
    145124 *  - If a line ends in a backslash, the backslash is stripped and the 
    146125 *    next line is appended. 
     
    153132 * 
    154133 * The caller is responsible for releasing the returned buffer by passing 
    155  * it to =free. 
     134 * it to =!free. 
     135 * 
     136 *>openpam_readlinev 
     137 *>openpam_readword 
    156138 */ 
  • trunk/lib/openpam_straddch.c

    r536 r547  
    1212 *    notice, this list of conditions and the following disclaimer in the 
    1313 *    documentation and/or other materials provided with the distribution. 
     14 * 3. The name of the author may not be used to endorse or promote 
     15 *    products derived from this software without specific prior written 
     16 *    permission. 
    1417 * 
    1518 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 
     
    3235#endif 
    3336 
     37#include <errno.h> 
    3438#include <stdlib.h> 
    3539 
     
    5761                if ((tmpstr = malloc(tmpsize)) == NULL) { 
    5862                        openpam_log(PAM_LOG_ERROR, "malloc(): %m"); 
     63                        errno = ENOMEM; 
    5964                        return (-1); 
    6065                } 
     
    6772                if ((tmpstr = realloc(*str, tmpsize)) == NULL) { 
    6873                        openpam_log(PAM_LOG_ERROR, "realloc(): %m"); 
     74                        errno = ENOMEM; 
    6975                        return (-1); 
    7076                } 
     
    100106 * integer variable pointed to by =len and returns 0. 
    101107 * Otherwise, it leaves the variables pointed to by =str, =size and =len 
    102  * unmodified and returns -1. 
     108 * unmodified, sets :errno to =ENOMEM and returns -1. 
    103109 */ 
Note: See TracChangeset for help on using the changeset viewer.