1 /* This file is part of pam-modules. 2 Copyright (C) 2008, 2010-2012, 2014-2015, 2018 Sergey Poznyakoff 3 4 This program is free software; you can redistribute it and/or modify it 5 under the terms of the GNU General Public License as published by the 6 Free Software Foundation; either version 3 of the License, or (at your 7 option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License along 15 with this program. If not, see <http://www.gnu.org/licenses/>. */ 16 17 #include <graypam.h> 18 19 static struct pam_opt * 20 find_opt(struct pam_opt *opt, const char *str, const char **value) 21 { 22 size_t len = strlen(str); 23 int isbool; 24 25 if (len > 2 && memcmp(str, "no", 2) == 0) { 26 *value = NULL; 27 str += 2; 28 isbool = 1; 29 } else { 30 isbool = 0; 31 *value = str; 32 } 33 34 for (; opt->name; opt++) { 35 if (len >= opt->len 36 && memcmp(opt->name, str, opt->len) == 0 37 && (!isbool || opt->type == pam_opt_bool)) { 38 int eq = str[opt->len] == '='; 39 40 switch (opt->type) { 41 case pam_opt_long: 42 case pam_opt_string: 43 case pam_opt_enum: 44 if (!eq) 45 continue; 46 *value = str + opt->len + 1; 47 break; 48 49 case pam_opt_null: 50 if (eq) 51 *value = str + opt->len + 1; 52 else 53 *value = NULL; 54 break; 55 56 default: 57 if (eq) 58 continue; 59 break; 60 } 61 return opt; 62 } 63 } 64 return NULL; 65 } 66 67 int 68 find_value(const char **enumstr, const char *value) 69 { 70 int i; 71 for (i = 0; *enumstr; enumstr++, i++) 72 if (strcmp(*enumstr, value) == 0) 73 return i; 74 return -1; 75 } 76 77 int 78 gray_parseopt(struct pam_opt *opt, int argc, const char **argv) 79 { 80 long n; 81 char *s; 82 int i; 83 int rc = 0; 84 85 for (i = 0; i < argc; ++i, ++argv) { 86 const char *value; 87 struct pam_opt *p = find_opt(opt, *argv, &value); 88 89 if (!p) { 90 _pam_log(LOG_ERR, 91 "%s: unknown option", *argv); 92 rc = 1; 93 continue; 94 } 95 96 switch (p->type) { 97 case pam_opt_long: 98 n = strtol(value, &s, 0); 99 if (*s) { 100 _pam_log(LOG_ERR, 101 "%s: %s is not a valid number", 102 p->name, value); 103 rc = 1; 104 continue; 105 } 106 *(long*)p->data = n; 107 break; 108 109 case pam_opt_const: 110 *(long*)p->data = p->v.value; 111 break; 112 113 case pam_opt_string: 114 *(const char**)p->data = value; 115 break; 116 117 case pam_opt_bool: 118 if (p->v.value) { 119 if (value) 120 *(int*)p->data |= p->v.value; 121 else 122 *(int*)p->data &= ~p->v.value; 123 } else 124 *(int*)p->data = value != NULL; 125 break; 126 127 case pam_opt_bitmask: 128 *(int*)p->data |= p->v.value; 129 break; 130 131 case pam_opt_bitmask_rev: 132 *(int*)p->data &= ~p->v.value; 133 break; 134 135 case pam_opt_enum: 136 n = find_value(p->v.enumstr, value); 137 if (n == -1) { 138 _pam_log(LOG_ERR, 139 "%s: invalid value %s", 140 p->name, value); 141 rc = 1; 142 continue; 143 } 144 *(int*)p->data = n; 145 break; 146 147 case pam_opt_rest: 148 *(int*)p->data = i + 1; 149 return 0; 150 151 case pam_opt_null: 152 break; 153 } 154 155 if (p->func && p->func (p, value)) 156 rc = 1; 157 } 158 return rc; 159 } 160