Home | History | Annotate | Line # | Download | only in libpam
      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