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