openpam_subst.c revision 1.3
1/*	$NetBSD: openpam_subst.c,v 1.3 2017/05/06 19:50:09 christos Exp $	*/
2
3/*-
4 * Copyright (c) 2011 Dag-Erling Sm��rgrav
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 * 3. The name of the author may not be used to endorse or promote
16 *    products derived from this software without specific prior written
17 *    permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 * $OpenPAM: openpam_subst.c 938 2017-04-30 21:34:42Z des $
32 */
33
34#ifdef HAVE_CONFIG_H
35# include "config.h"
36#endif
37
38#include <sys/cdefs.h>
39__RCSID("$NetBSD: openpam_subst.c,v 1.3 2017/05/06 19:50:09 christos Exp $");
40
41#include <security/pam_appl.h>
42
43#include "openpam_impl.h"
44
45#define subst_char(ch) do {			\
46	char ch_ = (ch);			\
47	if (buf && len < *bufsize)		\
48		*buf++ = ch_;			\
49	++len;					\
50} while (/*CONSTCOND*/0)
51
52#define subst_string(s) do {			\
53	const char *s_ = (s);			\
54	while (*s_)				\
55		subst_char(*s_++);		\
56} while (/*CONSTCOND*/0)
57
58#define subst_item(i) do {			\
59	int i_ = (i);				\
60	const void *p_;				\
61	ret = pam_get_item(pamh, i_, &p_);	\
62	if (ret == PAM_SUCCESS && p_ != NULL)	\
63		subst_string(p_);		\
64} while (/*CONSTCOND*/0)
65
66/*
67 * OpenPAM internal
68 *
69 * Substitute PAM item values in a string
70 */
71
72int
73openpam_subst(const pam_handle_t *pamh,
74    char *buf, size_t *bufsize, const char *template)
75{
76	size_t len;
77	int ret;
78
79	ENTERS(template);
80	if (template == NULL)
81		template = "(null)";
82
83	len = 1; /* initialize to 1 for terminating NUL */
84	ret = PAM_SUCCESS;
85	while (*template && ret == PAM_SUCCESS) {
86		if (template[0] == '%') {
87			++template;
88			switch (*template) {
89			case 's':
90				subst_item(PAM_SERVICE);
91				break;
92			case 't':
93				subst_item(PAM_TTY);
94				break;
95			case 'h':
96				subst_item(PAM_HOST);
97				break;
98			case 'u':
99				subst_item(PAM_USER);
100				break;
101			case 'H':
102				subst_item(PAM_RHOST);
103				break;
104			case 'U':
105				subst_item(PAM_RUSER);
106				break;
107			case '\0':
108				subst_char('%');
109				break;
110			default:
111				subst_char('%');
112				subst_char(*template);
113			}
114			++template;
115		} else {
116			subst_char(*template++);
117		}
118	}
119	if (buf)
120		*buf = '\0';
121	if (ret == PAM_SUCCESS) {
122		if (len > *bufsize)
123			ret = PAM_TRY_AGAIN;
124		*bufsize = len;
125	}
126	RETURNC(ret);
127}
128
129/*
130 * Error codes:
131 *
132 *	=pam_get_item
133 *	!PAM_SYMBOL_ERR
134 *	PAM_TRY_AGAIN
135 */
136
137/**
138 * The =openpam_subst function expands a string, substituting PAM item
139 * values for all occurrences of specific substitution codes.
140 * The =template argument points to the initial string.
141 * The result is stored in the buffer pointed to by the =buf argument; the
142 * =bufsize argument specifies the size of that buffer.
143 * The actual size of the resulting string, including the terminating NUL
144 * character, is stored in the location pointed to by the =bufsize
145 * argument.
146 *
147 * If =buf is NULL, or if the buffer is too small to hold the expanded
148 * string, =bufsize is updated to reflect the amount of space required to
149 * hold the entire string, and =openpam_subst returns =PAM_TRY_AGAIN.
150 *
151 * If =openpam_subst fails for any other reason, the =bufsize argument is
152 * untouched, but part of the buffer may still have been overwritten.
153 *
154 * Substitution codes are introduced by a percent character and correspond
155 * to PAM items:
156 *
157 *	%H:
158 *		Replaced by the current value of the =PAM_RHOST item.
159 *	%h:
160 *		Replaced by the current value of the =PAM_HOST item.
161 *	%s:
162 *		Replaced by the current value of the =PAM_SERVICE item.
163 *	%t:
164 *		Replaced by the current value of the =PAM_TTY item.
165 *	%U:
166 *		Replaced by the current value of the =PAM_RUSER item.
167 *	%u:
168 *		Replaced by the current value of the =PAM_USER item.
169 *
170 * >pam_get_authtok
171 * >pam_get_item
172 * >pam_get_user
173 *
174 * AUTHOR DES
175 */
176