1 /* $NetBSD: pam_std_option.c,v 1.2 2004/12/12 08:18:43 christos Exp $ */ 2 3 /*- 4 * Copyright 1998 Juniper Networks, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 #ifdef __FreeBSD__ 31 __FBSDID("$FreeBSD: src/lib/libpam/libpam/pam_std_option.c,v 1.10 2002/04/14 18:30:03 des Exp $"); 32 #else 33 __RCSID("$NetBSD: pam_std_option.c,v 1.2 2004/12/12 08:18:43 christos Exp $"); 34 #endif 35 36 #include <stdio.h> 37 #include <string.h> 38 #include <syslog.h> 39 40 #include <security/pam_appl.h> 41 #include <security/pam_mod_misc.h> 42 43 /* Everyone has to have these options. It is not an error to 44 * specify them and then not use them. 45 */ 46 struct opttab std_options[PAM_MAX_OPTIONS] = { 47 { "debug", PAM_OPT_DEBUG }, 48 { "no_warn", PAM_OPT_NO_WARN }, 49 { "echo_pass", PAM_OPT_ECHO_PASS }, 50 { "use_first_pass", PAM_OPT_USE_FIRST_PASS }, 51 { "try_first_pass", PAM_OPT_TRY_FIRST_PASS }, 52 { "use_mapped_pass", PAM_OPT_USE_MAPPED_PASS }, 53 { "try_mapped_pass", PAM_OPT_TRY_MAPPED_PASS }, 54 { "expose_account", PAM_OPT_EXPOSE_ACCOUNT }, 55 { NULL, 0 } 56 }; 57 58 /* Populate the options structure, syslogging all errors */ 59 void 60 pam_std_option(struct options *options, struct opttab other_options[], 61 int argc, const char *argv[]) 62 { 63 struct opttab *oo; 64 int i, j, std, extra, arglen, found; 65 66 std = 1; 67 extra = 1; 68 oo = other_options; 69 for (i = 0; i < PAM_MAX_OPTIONS; i++) { 70 if (std && std_options[i].name == NULL) 71 std = 0; 72 else if (extra && (oo == NULL || oo->name == NULL)) 73 extra = 0; 74 75 if (std) 76 options->opt[i].name = std_options[i].name; 77 else if (extra) { 78 if (oo->value != i) 79 syslog(LOG_DEBUG, "Extra option fault: %d %d", 80 oo->value, i); 81 options->opt[i].name = oo->name; 82 oo++; 83 } 84 else 85 options->opt[i].name = NULL; 86 87 options->opt[i].bool = 0; 88 options->opt[i].arg = NULL; 89 } 90 91 for (j = 0; j < argc; j++) { 92 #ifdef DEBUG 93 syslog(LOG_DEBUG, "Doing arg %s", argv[j]); 94 #endif 95 found = 0; 96 for (i = 0; i < PAM_MAX_OPTIONS; i++) { 97 if (options->opt[i].name == NULL) 98 break; 99 arglen = strlen(options->opt[i].name); 100 if (strcmp(argv[j], options->opt[i].name) == 0) { 101 options->opt[i].bool = 1; 102 found = 1; 103 break; 104 } 105 else if (strncmp(argv[j], options->opt[i].name, arglen) 106 == 0 && argv[j][arglen] == '=') { 107 options->opt[i].bool = 1; 108 options->opt[i].arg 109 = strdup(&argv[j][arglen + 1]); 110 found = 1; 111 break; 112 } 113 } 114 if (!found) 115 syslog(LOG_WARNING, "PAM option: %s invalid", argv[j]); 116 } 117 } 118 119 /* Test if option is set in options */ 120 int 121 pam_test_option(struct options *options, enum opt option, char **arg) 122 { 123 if (arg != NULL) 124 *arg = options->opt[option].arg; 125 return options->opt[option].bool; 126 } 127 128 /* Set option in options, errors to syslog */ 129 void 130 pam_set_option(struct options *options, enum opt option) 131 { 132 if (option < PAM_OPT_STD_MAX) 133 options->opt[option].bool = 1; 134 #ifdef DEBUG 135 else 136 syslog(LOG_DEBUG, "PAM options: attempt to set option %d", 137 option); 138 #endif 139 } 140 141 /* Clear option in options, errors to syslog */ 142 void 143 pam_clear_option(struct options *options, enum opt option) 144 { 145 if (option < PAM_OPT_STD_MAX) 146 options->opt[option].bool = 0; 147 #ifdef DEBUG 148 else 149 syslog(LOG_DEBUG, "PAM options: attempt to clear option %d", 150 option); 151 #endif 152 } 153 154 #ifdef DEBUG1 155 enum { PAM_OPT_FOO=PAM_OPT_STD_MAX, PAM_OPT_BAR, PAM_OPT_BAZ, PAM_OPT_QUX }; 156 157 struct opttab other_options[] = { 158 { "foo", PAM_OPT_FOO }, 159 { "bar", PAM_OPT_BAR }, 160 { "baz", PAM_OPT_BAZ }, 161 { "qux", PAM_OPT_QUX }, 162 { NULL, 0 } 163 }; 164 165 int 166 main(int argc, const char *argv[]) 167 { 168 struct options options; 169 int i, opt; 170 char *arg; 171 172 pam_std_option(&options, other_options, argc, argv); 173 for (i = 0; i < PAM_MAX_OPTIONS; i++) { 174 opt = pam_test_option(&options, i, &arg); 175 if (opt) { 176 if (arg == NULL) 177 printf("%d []\n", i); 178 else 179 printf("%d [%s]\n", i, arg); 180 } 181 } 182 return 0; 183 } 184 #endif 185