xref: /netbsd-src/external/bsd/openpam/dist/lib/libpam/openpam_subst.c (revision 0d9d0fd8a30be9a1924e715bbcf67a4a83efd262)
1*0d9d0fd8Schristos /*	$NetBSD: openpam_subst.c,v 1.4 2023/06/30 21:46:21 christos Exp $	*/
2201780c4Schristos 
376e8c542Schristos /*-
4*0d9d0fd8Schristos  * Copyright (c) 2011-2023 Dag-Erling Smørgrav
576e8c542Schristos  * All rights reserved.
676e8c542Schristos  *
776e8c542Schristos  * Redistribution and use in source and binary forms, with or without
876e8c542Schristos  * modification, are permitted provided that the following conditions
976e8c542Schristos  * are met:
1076e8c542Schristos  * 1. Redistributions of source code must retain the above copyright
1176e8c542Schristos  *    notice, this list of conditions and the following disclaimer.
1276e8c542Schristos  * 2. Redistributions in binary form must reproduce the above copyright
1376e8c542Schristos  *    notice, this list of conditions and the following disclaimer in the
1476e8c542Schristos  *    documentation and/or other materials provided with the distribution.
1576e8c542Schristos  * 3. The name of the author may not be used to endorse or promote
1676e8c542Schristos  *    products derived from this software without specific prior written
1776e8c542Schristos  *    permission.
1876e8c542Schristos  *
1976e8c542Schristos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2076e8c542Schristos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2176e8c542Schristos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2276e8c542Schristos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2376e8c542Schristos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2476e8c542Schristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2576e8c542Schristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2676e8c542Schristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2776e8c542Schristos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2876e8c542Schristos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2976e8c542Schristos  * SUCH DAMAGE.
3076e8c542Schristos  */
3176e8c542Schristos 
3276e8c542Schristos #ifdef HAVE_CONFIG_H
3376e8c542Schristos # include "config.h"
3476e8c542Schristos #endif
3576e8c542Schristos 
36201780c4Schristos #include <sys/cdefs.h>
37*0d9d0fd8Schristos __RCSID("$NetBSD: openpam_subst.c,v 1.4 2023/06/30 21:46:21 christos Exp $");
38201780c4Schristos 
3976e8c542Schristos #include <security/pam_appl.h>
4076e8c542Schristos 
4176e8c542Schristos #include "openpam_impl.h"
4276e8c542Schristos 
4376e8c542Schristos #define subst_char(ch) do {			\
44201780c4Schristos 	char ch_ = (ch);			\
4576e8c542Schristos 	if (buf && len < *bufsize)		\
4676e8c542Schristos 		*buf++ = ch_;			\
4776e8c542Schristos 	++len;					\
48201780c4Schristos } while (/*CONSTCOND*/0)
4976e8c542Schristos 
5076e8c542Schristos #define subst_string(s) do {			\
5176e8c542Schristos 	const char *s_ = (s);			\
5276e8c542Schristos 	while (*s_)				\
5376e8c542Schristos 		subst_char(*s_++);		\
54201780c4Schristos } while (/*CONSTCOND*/0)
5576e8c542Schristos 
5676e8c542Schristos #define subst_item(i) do {			\
5776e8c542Schristos 	int i_ = (i);				\
5876e8c542Schristos 	const void *p_;				\
5976e8c542Schristos 	ret = pam_get_item(pamh, i_, &p_);	\
6076e8c542Schristos 	if (ret == PAM_SUCCESS && p_ != NULL)	\
6176e8c542Schristos 		subst_string(p_);		\
62201780c4Schristos } while (/*CONSTCOND*/0)
6376e8c542Schristos 
6476e8c542Schristos /*
6576e8c542Schristos  * OpenPAM internal
6676e8c542Schristos  *
6776e8c542Schristos  * Substitute PAM item values in a string
6876e8c542Schristos  */
6976e8c542Schristos 
7076e8c542Schristos int
openpam_subst(const pam_handle_t * pamh,char * buf,size_t * bufsize,const char * template)7176e8c542Schristos openpam_subst(const pam_handle_t *pamh,
7276e8c542Schristos     char *buf, size_t *bufsize, const char *template)
7376e8c542Schristos {
7476e8c542Schristos 	size_t len;
7576e8c542Schristos 	int ret;
7676e8c542Schristos 
7776e8c542Schristos 	ENTERS(template);
7876e8c542Schristos 	if (template == NULL)
7976e8c542Schristos 		template = "(null)";
8076e8c542Schristos 
8176e8c542Schristos 	len = 1; /* initialize to 1 for terminating NUL */
8276e8c542Schristos 	ret = PAM_SUCCESS;
8376e8c542Schristos 	while (*template && ret == PAM_SUCCESS) {
8476e8c542Schristos 		if (template[0] == '%') {
8576e8c542Schristos 			++template;
8676e8c542Schristos 			switch (*template) {
8776e8c542Schristos 			case 's':
8876e8c542Schristos 				subst_item(PAM_SERVICE);
8976e8c542Schristos 				break;
9076e8c542Schristos 			case 't':
9176e8c542Schristos 				subst_item(PAM_TTY);
9276e8c542Schristos 				break;
9376e8c542Schristos 			case 'h':
9476e8c542Schristos 				subst_item(PAM_HOST);
9576e8c542Schristos 				break;
9676e8c542Schristos 			case 'u':
9776e8c542Schristos 				subst_item(PAM_USER);
9876e8c542Schristos 				break;
9976e8c542Schristos 			case 'H':
10076e8c542Schristos 				subst_item(PAM_RHOST);
10176e8c542Schristos 				break;
10276e8c542Schristos 			case 'U':
10376e8c542Schristos 				subst_item(PAM_RUSER);
10476e8c542Schristos 				break;
10576e8c542Schristos 			case '\0':
10676e8c542Schristos 				subst_char('%');
10776e8c542Schristos 				break;
10876e8c542Schristos 			default:
10976e8c542Schristos 				subst_char('%');
11076e8c542Schristos 				subst_char(*template);
11176e8c542Schristos 			}
112*0d9d0fd8Schristos 			if (*template)
11376e8c542Schristos 				++template;
11476e8c542Schristos 		} else {
11576e8c542Schristos 			subst_char(*template++);
11676e8c542Schristos 		}
11776e8c542Schristos 	}
11876e8c542Schristos 	if (buf)
11976e8c542Schristos 		*buf = '\0';
12076e8c542Schristos 	if (ret == PAM_SUCCESS) {
12176e8c542Schristos 		if (len > *bufsize)
12276e8c542Schristos 			ret = PAM_TRY_AGAIN;
12376e8c542Schristos 		*bufsize = len;
12476e8c542Schristos 	}
12576e8c542Schristos 	RETURNC(ret);
12676e8c542Schristos }
12776e8c542Schristos 
12876e8c542Schristos /*
12976e8c542Schristos  * Error codes:
13076e8c542Schristos  *
13176e8c542Schristos  *	=pam_get_item
13276e8c542Schristos  *	!PAM_SYMBOL_ERR
13376e8c542Schristos  *	PAM_TRY_AGAIN
13476e8c542Schristos  */
13576e8c542Schristos 
13676e8c542Schristos /**
13776e8c542Schristos  * The =openpam_subst function expands a string, substituting PAM item
13876e8c542Schristos  * values for all occurrences of specific substitution codes.
13976e8c542Schristos  * The =template argument points to the initial string.
14076e8c542Schristos  * The result is stored in the buffer pointed to by the =buf argument; the
14176e8c542Schristos  * =bufsize argument specifies the size of that buffer.
14276e8c542Schristos  * The actual size of the resulting string, including the terminating NUL
14376e8c542Schristos  * character, is stored in the location pointed to by the =bufsize
14476e8c542Schristos  * argument.
14576e8c542Schristos  *
14676e8c542Schristos  * If =buf is NULL, or if the buffer is too small to hold the expanded
14776e8c542Schristos  * string, =bufsize is updated to reflect the amount of space required to
14876e8c542Schristos  * hold the entire string, and =openpam_subst returns =PAM_TRY_AGAIN.
14976e8c542Schristos  *
15076e8c542Schristos  * If =openpam_subst fails for any other reason, the =bufsize argument is
15176e8c542Schristos  * untouched, but part of the buffer may still have been overwritten.
15276e8c542Schristos  *
15376e8c542Schristos  * Substitution codes are introduced by a percent character and correspond
15476e8c542Schristos  * to PAM items:
15576e8c542Schristos  *
15676e8c542Schristos  *	%H:
15776e8c542Schristos  *		Replaced by the current value of the =PAM_RHOST item.
15876e8c542Schristos  *	%h:
15976e8c542Schristos  *		Replaced by the current value of the =PAM_HOST item.
16076e8c542Schristos  *	%s:
16176e8c542Schristos  *		Replaced by the current value of the =PAM_SERVICE item.
16276e8c542Schristos  *	%t:
16376e8c542Schristos  *		Replaced by the current value of the =PAM_TTY item.
16476e8c542Schristos  *	%U:
16576e8c542Schristos  *		Replaced by the current value of the =PAM_RUSER item.
16676e8c542Schristos  *	%u:
16776e8c542Schristos  *		Replaced by the current value of the =PAM_USER item.
16876e8c542Schristos  *
16976e8c542Schristos  * >pam_get_authtok
17076e8c542Schristos  * >pam_get_item
17176e8c542Schristos  * >pam_get_user
17276e8c542Schristos  *
17376e8c542Schristos  * AUTHOR DES
17476e8c542Schristos  */
175