/* $NetBSD: pam_std_option.c,v 1.2 2004/12/12 08:18:43 christos Exp $ */ /*- * Copyright 1998 Juniper Networks, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #ifdef __FreeBSD__ __FBSDID("$FreeBSD: src/lib/libpam/libpam/pam_std_option.c,v 1.10 2002/04/14 18:30:03 des Exp $"); #else __RCSID("$NetBSD: pam_std_option.c,v 1.2 2004/12/12 08:18:43 christos Exp $"); #endif #include #include #include #include #include /* Everyone has to have these options. It is not an error to * specify them and then not use them. */ struct opttab std_options[PAM_MAX_OPTIONS] = { { "debug", PAM_OPT_DEBUG }, { "no_warn", PAM_OPT_NO_WARN }, { "echo_pass", PAM_OPT_ECHO_PASS }, { "use_first_pass", PAM_OPT_USE_FIRST_PASS }, { "try_first_pass", PAM_OPT_TRY_FIRST_PASS }, { "use_mapped_pass", PAM_OPT_USE_MAPPED_PASS }, { "try_mapped_pass", PAM_OPT_TRY_MAPPED_PASS }, { "expose_account", PAM_OPT_EXPOSE_ACCOUNT }, { NULL, 0 } }; /* Populate the options structure, syslogging all errors */ void pam_std_option(struct options *options, struct opttab other_options[], int argc, const char *argv[]) { struct opttab *oo; int i, j, std, extra, arglen, found; std = 1; extra = 1; oo = other_options; for (i = 0; i < PAM_MAX_OPTIONS; i++) { if (std && std_options[i].name == NULL) std = 0; else if (extra && (oo == NULL || oo->name == NULL)) extra = 0; if (std) options->opt[i].name = std_options[i].name; else if (extra) { if (oo->value != i) syslog(LOG_DEBUG, "Extra option fault: %d %d", oo->value, i); options->opt[i].name = oo->name; oo++; } else options->opt[i].name = NULL; options->opt[i].bool = 0; options->opt[i].arg = NULL; } for (j = 0; j < argc; j++) { #ifdef DEBUG syslog(LOG_DEBUG, "Doing arg %s", argv[j]); #endif found = 0; for (i = 0; i < PAM_MAX_OPTIONS; i++) { if (options->opt[i].name == NULL) break; arglen = strlen(options->opt[i].name); if (strcmp(argv[j], options->opt[i].name) == 0) { options->opt[i].bool = 1; found = 1; break; } else if (strncmp(argv[j], options->opt[i].name, arglen) == 0 && argv[j][arglen] == '=') { options->opt[i].bool = 1; options->opt[i].arg = strdup(&argv[j][arglen + 1]); found = 1; break; } } if (!found) syslog(LOG_WARNING, "PAM option: %s invalid", argv[j]); } } /* Test if option is set in options */ int pam_test_option(struct options *options, enum opt option, char **arg) { if (arg != NULL) *arg = options->opt[option].arg; return options->opt[option].bool; } /* Set option in options, errors to syslog */ void pam_set_option(struct options *options, enum opt option) { if (option < PAM_OPT_STD_MAX) options->opt[option].bool = 1; #ifdef DEBUG else syslog(LOG_DEBUG, "PAM options: attempt to set option %d", option); #endif } /* Clear option in options, errors to syslog */ void pam_clear_option(struct options *options, enum opt option) { if (option < PAM_OPT_STD_MAX) options->opt[option].bool = 0; #ifdef DEBUG else syslog(LOG_DEBUG, "PAM options: attempt to clear option %d", option); #endif } #ifdef DEBUG1 enum { PAM_OPT_FOO=PAM_OPT_STD_MAX, PAM_OPT_BAR, PAM_OPT_BAZ, PAM_OPT_QUX }; struct opttab other_options[] = { { "foo", PAM_OPT_FOO }, { "bar", PAM_OPT_BAR }, { "baz", PAM_OPT_BAZ }, { "qux", PAM_OPT_QUX }, { NULL, 0 } }; int main(int argc, const char *argv[]) { struct options options; int i, opt; char *arg; pam_std_option(&options, other_options, argc, argv); for (i = 0; i < PAM_MAX_OPTIONS; i++) { opt = pam_test_option(&options, i, &arg); if (opt) { if (arg == NULL) printf("%d []\n", i); else printf("%d [%s]\n", i, arg); } } return 0; } #endif