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
pam_std_option(struct options * options,struct opttab other_options[],int argc,const char * argv[])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
pam_test_option(struct options * options,enum opt option,char ** arg)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
pam_set_option(struct options * options,enum opt option)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
pam_clear_option(struct options * options,enum opt option)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
main(int argc,const char * argv[])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