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