1121054Semax/*- 2121054Semax * Copyright (c) 2011-2023 Dag-Erling Sm��rgrav 3121054Semax * All rights reserved. 4121054Semax * 5121054Semax * Redistribution and use in source and binary forms, with or without 6121054Semax * modification, are permitted provided that the following conditions 7121054Semax * are met: 8121054Semax * 1. Redistributions of source code must retain the above copyright 9121054Semax * notice, this list of conditions and the following disclaimer. 10121054Semax * 2. Redistributions in binary form must reproduce the above copyright 11121054Semax * notice, this list of conditions and the following disclaimer in the 12121054Semax * documentation and/or other materials provided with the distribution. 13121054Semax * 3. The name of the author may not be used to endorse or promote 14121054Semax * products derived from this software without specific prior written 15121054Semax * permission. 16121054Semax * 17121054Semax * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18121054Semax * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19121054Semax * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20121054Semax * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21121054Semax * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22121054Semax * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23121054Semax * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24121054Semax * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25121054Semax * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26121054Semax * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27121054Semax * SUCH DAMAGE. 28121054Semax */ 29121054Semax 30121054Semax#ifdef HAVE_CONFIG_H 31121054Semax# include "config.h" 32121054Semax#endif 33121054Semax 34121054Semax#include <security/pam_appl.h> 35121054Semax 36121054Semax#include "openpam_impl.h" 37121054Semax 38121054Semax#define subst_char(ch) do { \ 39121054Semax int ch_ = (ch); \ 40121054Semax if (buf && len < *bufsize) \ 41121054Semax *buf++ = ch_; \ 42121054Semax ++len; \ 43121054Semax} while (0) 44124317Semax 45124317Semax#define subst_string(s) do { \ 46121054Semax const char *s_ = (s); \ 47121054Semax while (*s_) \ 48121054Semax subst_char(*s_++); \ 49121054Semax} while (0) 50121054Semax 51121054Semax#define subst_item(i) do { \ 52121054Semax int i_ = (i); \ 53121054Semax const void *p_; \ 54121054Semax ret = pam_get_item(pamh, i_, &p_); \ 55124317Semax if (ret == PAM_SUCCESS && p_ != NULL) \ 56124317Semax subst_string(p_); \ 57124317Semax} while (0) 58121054Semax 59121054Semax/* 60124758Semax * OpenPAM internal 61121054Semax * 62121054Semax * Substitute PAM item values in a string 63124317Semax */ 64121054Semax 65124317Semaxint 66121054Semaxopenpam_subst(const pam_handle_t *pamh, 67121054Semax char *buf, size_t *bufsize, const char *template) 68121054Semax{ 69121054Semax size_t len; 70121054Semax int ret; 71121054Semax 72121054Semax ENTERS(template); 73121054Semax if (template == NULL) 74121054Semax template = "(null)"; 75121054Semax 76124317Semax len = 1; /* initialize to 1 for terminating NUL */ 77124317Semax ret = PAM_SUCCESS; 78124317Semax while (*template && ret == PAM_SUCCESS) { 79124317Semax if (template[0] == '%') { 80124317Semax ++template; 81124317Semax switch (*template) { 82124317Semax case 's': 83124317Semax subst_item(PAM_SERVICE); 84121054Semax break; 85121054Semax case 't': 86121054Semax subst_item(PAM_TTY); 87121054Semax break; 88121054Semax case 'h': 89121054Semax subst_item(PAM_HOST); 90121054Semax break; 91121054Semax case 'u': 92121054Semax subst_item(PAM_USER); 93121054Semax break; 94121054Semax case 'H': 95121054Semax subst_item(PAM_RHOST); 96121054Semax break; 97124317Semax case 'U': 98121054Semax subst_item(PAM_RUSER); 99121054Semax break; 100121054Semax case '\0': 101121054Semax subst_char('%'); 102124317Semax break; 103124317Semax default: 104121054Semax subst_char('%'); 105121054Semax subst_char(*template); 106121054Semax } 107121054Semax if (*template) 108121054Semax ++template; 109121054Semax } else { 110121054Semax subst_char(*template++); 111121054Semax } 112121054Semax } 113121054Semax if (buf) 114121054Semax *buf = '\0'; 115121054Semax if (ret == PAM_SUCCESS) { 116121054Semax if (len > *bufsize) 117121054Semax ret = PAM_TRY_AGAIN; 118121054Semax *bufsize = len; 119121054Semax } 120121054Semax RETURNC(ret); 121121054Semax} 122121054Semax 123121054Semax/* 124121054Semax * Error codes: 125121054Semax * 126121054Semax * =pam_get_item 127121054Semax * !PAM_SYMBOL_ERR 128121054Semax * PAM_TRY_AGAIN 129121054Semax */ 130121054Semax 131121054Semax/** 132121054Semax * The =openpam_subst function expands a string, substituting PAM item 133121054Semax * values for all occurrences of specific substitution codes. 134121054Semax * The =template argument points to the initial string. 135124317Semax * The result is stored in the buffer pointed to by the =buf argument; the 136124317Semax * =bufsize argument specifies the size of that buffer. 137124317Semax * The actual size of the resulting string, including the terminating NUL 138121054Semax * character, is stored in the location pointed to by the =bufsize 139124317Semax * argument. 140124317Semax * 141124317Semax * If =buf is NULL, or if the buffer is too small to hold the expanded 142124317Semax * string, =bufsize is updated to reflect the amount of space required to 143124317Semax * hold the entire string, and =openpam_subst returns =PAM_TRY_AGAIN. 144121054Semax * 145121054Semax * If =openpam_subst fails for any other reason, the =bufsize argument is 146121054Semax * untouched, but part of the buffer may still have been overwritten. 147121054Semax * 148121054Semax * Substitution codes are introduced by a percent character and correspond 149121054Semax * to PAM items: 150121054Semax * 151121054Semax * %H: 152121054Semax * Replaced by the current value of the =PAM_RHOST item. 153121054Semax * %h: 154121054Semax * Replaced by the current value of the =PAM_HOST item. 155121054Semax * %s: 156121054Semax * Replaced by the current value of the =PAM_SERVICE item. 157121054Semax * %t: 158121054Semax * Replaced by the current value of the =PAM_TTY item. 159121054Semax * %U: 160121054Semax * Replaced by the current value of the =PAM_RUSER item. 161121054Semax * %u: 162121054Semax * Replaced by the current value of the =PAM_USER item. 163121054Semax * 164121054Semax * >pam_get_authtok 165121054Semax * >pam_get_item 166121054Semax * >pam_get_user 167121054Semax * 168121054Semax * AUTHOR DES 169121054Semax */ 170121054Semax