1 /* pam_misc.c -- This is random stuff */
3 /* $Id: pam_misc.c,v 1.9 1997/04/05 06:56:19 morgan Exp $
4 * $FreeBSD: src/contrib/libpam/libpam/pam_misc.c,v 1.1.1.1.6.3 2001/09/13 08:24:14 roam Exp $
7 * Revision 1.9 1997/04/05 06:56:19 morgan
8 * enforce AUTHTOK restrictions
10 * Revision 1.8 1997/02/15 15:59:46 morgan
11 * modified ..strCMP comment
13 * Revision 1.7 1996/12/01 03:14:13 morgan
16 * Revision 1.6 1996/11/10 20:05:52 morgan
17 * name convention _pam_ enforced. Also modified _pam_strdup()
19 * Revision 1.5 1996/07/07 23:57:14 morgan
20 * deleted debuggin function and replaced it with a static function
21 * defined in pam_private.h
23 * Revision 1.4 1996/06/02 08:00:56 morgan
24 * added StrTok function
26 * Revision 1.3 1996/05/21 04:36:58 morgan
27 * added debugging information
28 * replaced the _pam_log need for a local buffer with a call to vsyslog()
29 * [Al Longyear had some segfaulting problems related to this]
31 * Revision 1.2 1996/03/16 21:55:13 morgan
32 * changed pam_mkargv to _pam_mkargv
43 #include "pam_private.h"
45 /* caseless string comparison: POSIX does not define this.. */
46 int _pam_strCMP(const char *s, const char *t)
51 cf = tolower(*s) - tolower(*t);
53 } while (!cf && *s++);
58 char *_pam_StrTok(char *from, const char *format, char **next)
60 * this function is a variant of the standard strtok, it differs in that
61 * it takes an additional argument and doesn't nul terminate tokens until
62 * they are actually reached.
65 char table[256], *end;
68 if (from == NULL && (from = *next) == NULL)
71 /* initialize table */
72 for (i=1; i<256; table[i++] = '\0');
73 for (i=0; format[i] ; table[(int)format[i++]] = 'y');
75 /* look for first non-blank char */
76 while (*from && table[(int)*from]) {
82 * special case, "[...]" is considered to be a single
83 * object. Note, however, if one of the format[] chars is
84 * '[' this single string will not be read correctly.
86 for (end=++from; *end && *end != ']'; ++end) {
87 if (*end == '\\' && end[1] == ']')
90 /* note, this string is stripped of its edges: "..." is what
93 /* simply look for next blank char */
94 for (end=from; *end && !table[(int)*end]; ++end);
96 return (*next = NULL); /* no tokens left */
99 /* now terminate what we have */
103 /* indicate what it left */
107 *next = NULL; /* have found last token */
110 /* return what we have */
115 * Safe duplication of character strings. "Paranoid"; don't leave
116 * evidence of old token around for later stack analysis.
119 char *_pam_strdup(const char *x)
121 register char *new=NULL;
126 for (i=0; x[i]; ++i); /* length of string */
127 if ((new = malloc(++i)) == NULL) {
129 pam_system_log(NULL, NULL, LOG_CRIT,
130 "_pam_strdup: failed to get memory");
139 return new; /* return the duplicate or NULL on error */
142 /* Generate argv, argc from s */
143 /* caller must free(argv) */
145 int _pam_mkargv(char *s, char ***argv, int *argc)
149 char *sbuf, *sbuf_start;
150 char **our_argv = NULL;
157 D(("_pam_mkargv called: %s",s));
163 if ((sbuf = sbuf_start = _pam_strdup(s)) == NULL) {
164 pam_system_log(NULL, NULL, LOG_CRIT,
165 "pam_mkargv: null returned by _pam_strdup");
168 /* Overkill on the malloc, but not large */
169 argvlen = (l + 1) * ((sizeof(char)) + sizeof(char *));
170 if ((our_argv = argvbuf = malloc(argvlen)) == NULL) {
171 pam_system_log(NULL, NULL, LOG_CRIT,
172 "pam_mkargv: null returned by malloc");
176 argvbufp = (char *) argvbuf + (l * sizeof(char *));
178 while ((sbuf = _pam_StrTok(sbuf, " \n\t", &tmp))) {
179 D(("arg #%d",++count));
181 strcpy(argvbufp, sbuf);
184 argvbufp += strlen(argvbufp) + 1;
185 D(("stepped in argvbufp"));
191 _pam_drop(sbuf_start);
198 D(("_pam_mkargv returned"));
204 * this function is used to protect the modules from accidental or
205 * semi-mallicious harm that an application may do to confuse the API.
208 void _pam_sanitize(pam_handle_t *pamh)
211 * this is for security. We reset the auth-tokens here.
213 pam_set_item(pamh,PAM_AUTHTOK,NULL);
214 pam_set_item(pamh,PAM_OLDAUTHTOK,NULL);
218 * This function scans the array and replaces the _PAM_ACTION_UNDEF
219 * entries with the default action.
222 void _pam_set_default_control(int *control_array, int default_action)
226 for (i=0; i<_PAM_RETURN_VALUES; ++i) {
227 if (control_array[i] == _PAM_ACTION_UNDEF) {
228 control_array[i] = default_action;
234 * This function is used to parse a control string. This string is a
235 * series of tokens of the following form:
237 * "[ ]*return_code[ ]*=[ ]*action/[ ]".
240 #include "pam_tokens.h"
242 void _pam_parse_control(int *control_array, char *tok)
250 /* skip leading space */
251 while (isspace(*tok) && *++tok);
255 /* identify return code */
256 for (ret=0; ret<=_PAM_RETURN_VALUES; ++ret) {
257 len = strlen(_pam_token_returns[ret]);
258 if (!strncmp(_pam_token_returns[ret], tok, len)) {
262 if (ret > _PAM_RETURN_VALUES || !*(tok += len)) {
263 error = "expecting return value";
268 while (isspace(*tok) && *++tok);
269 if (!*tok || *tok++ != '=') {
270 error = "expecting '='";
274 /* skip leading space */
275 while (isspace(*tok) && *++tok);
277 error = "expecting action";
281 /* observe action type */
282 for (act=0; act < (-(_PAM_ACTION_UNDEF)); ++act) {
283 len = strlen(_pam_token_actions[act]);
284 if (!strncmp(_pam_token_actions[act], tok, len)) {
292 * Either we have a number or we have hit an error. In
293 * principle, there is nothing to stop us accepting
294 * negative offsets. (Although we would have to think of
295 * another way of encoding the tokens.) However, I really
296 * think this would be both hard to administer and easily
297 * cause looping problems. So, for now, we will just
298 * allow forward jumps. (AGM 1998/1/7)
300 if (!isdigit(*tok)) {
301 error = "expecting jump number";
308 act += *tok - '0'; /* XXX - this assumes ascii behavior */
309 } while (*++tok && isdigit(*tok));
311 /* we do not allow 0 jumps. There is a token ('ignore')
313 error = "expecting non-zero";
318 /* set control_array element */
319 if (ret != _PAM_RETURN_VALUES) {
320 control_array[ret] = act;
322 /* set the default to 'act' */
323 _pam_set_default_control(control_array, act);
327 /* that was a success */
331 /* treat everything as bad */
332 pam_system_log(NULL, NULL, LOG_ERR, "pam_parse: %s; [...%s]", error, tok);
333 for (ret=0; ret<_PAM_RETURN_VALUES; control_array[ret++]=_PAM_ACTION_BAD);