1236099Sdes/*- 2236099Sdes * Copyright (c) 2011 Dag-Erling Sm��rgrav 3236099Sdes * All rights reserved. 4236099Sdes * 5236099Sdes * Redistribution and use in source and binary forms, with or without 6236099Sdes * modification, are permitted provided that the following conditions 7236099Sdes * are met: 8236099Sdes * 1. Redistributions of source code must retain the above copyright 9255376Sdes * notice, this list of conditions and the following disclaimer. 10236099Sdes * 2. Redistributions in binary form must reproduce the above copyright 11236099Sdes * notice, this list of conditions and the following disclaimer in the 12236099Sdes * documentation and/or other materials provided with the distribution. 13236099Sdes * 3. The name of the author may not be used to endorse or promote 14236099Sdes * products derived from this software without specific prior written 15236099Sdes * permission. 16236099Sdes * 17236099Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18236099Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19236099Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20236099Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21236099Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22236099Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23236099Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24236099Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25236099Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26236099Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27236099Sdes * SUCH DAMAGE. 28236099Sdes * 29271947Sdes * $Id: openpam_dump_policy.c 798 2014-06-10 21:28:14Z des $ 30236099Sdes */ 31236099Sdes 32236099Sdes#ifdef HAVE_CONFIG_H 33236099Sdes# include "config.h" 34236099Sdes#endif 35236099Sdes 36236099Sdes#include <ctype.h> 37236099Sdes#include <stdio.h> 38236099Sdes#include <stdlib.h> 39236099Sdes#include <string.h> 40236099Sdes#include <unistd.h> 41236099Sdes 42236099Sdes#include <security/pam_appl.h> 43236099Sdes 44236099Sdes#include "openpam_impl.h" 45255376Sdes#include "openpam_asprintf.h" 46236099Sdes 47236099Sdesstatic char * 48236099Sdesopenpam_chain_name(const char *service, pam_facility_t fclt) 49236099Sdes{ 50236099Sdes const char *facility = pam_facility_name[fclt]; 51236099Sdes char *name; 52236099Sdes 53236099Sdes if (asprintf(&name, "pam_%s_%s", service, facility) == -1) 54236099Sdes return (NULL); 55236099Sdes return (name); 56236099Sdes} 57236099Sdes 58236099Sdesstatic char * 59236099Sdesopenpam_facility_index_name(pam_facility_t fclt) 60236099Sdes{ 61236099Sdes const char *facility = pam_facility_name[fclt]; 62236099Sdes char *name, *p; 63236099Sdes 64236099Sdes if (asprintf(&name, "PAM_%s", facility) == -1) 65236099Sdes return (NULL); 66236099Sdes for (p = name + 4; *p; ++p) 67271947Sdes *p = toupper((unsigned char)*p); 68236099Sdes return (name); 69236099Sdes} 70236099Sdes 71236099Sdesint 72236099Sdesopenpam_dump_chain(const char *name, pam_chain_t *chain) 73236099Sdes{ 74236099Sdes char *modname, **opt, *p; 75236099Sdes int i; 76236099Sdes 77236099Sdes for (i = 0; chain != NULL; ++i, chain = chain->next) { 78236099Sdes /* declare the module's struct pam_module */ 79236099Sdes modname = strrchr(chain->module->path, '/'); 80236099Sdes modname = strdup(modname ? modname : chain->module->path); 81236099Sdes if (modname == NULL) 82236099Sdes return (PAM_BUF_ERR); 83236099Sdes for (p = modname; *p && *p != '.'; ++p) 84236099Sdes /* nothing */ ; 85236099Sdes *p = '\0'; 86236099Sdes printf("extern struct pam_module %s_pam_module;\n", modname); 87236099Sdes /* module arguments */ 88236099Sdes printf("static char *%s_%d_optv[] = {\n", name, i); 89236099Sdes for (opt = chain->optv; *opt; ++opt) { 90236099Sdes printf("\t\""); 91236099Sdes for (p = *opt; *p; ++p) { 92236099Sdes if (isprint((unsigned char)*p) && *p != '"') 93236099Sdes printf("%c", *p); 94236099Sdes else 95236099Sdes printf("\\x%02x", (unsigned char)*p); 96236099Sdes } 97236099Sdes printf("\",\n"); 98236099Sdes } 99236099Sdes printf("\tNULL,\n"); 100236099Sdes printf("};\n"); 101236099Sdes /* next module in chain */ 102236099Sdes if (chain->next != NULL) 103236099Sdes printf("static pam_chain_t %s_%d;\n", name, i + 1); 104236099Sdes /* chain entry */ 105236099Sdes printf("static pam_chain_t %s_%d = {\n", name, i); 106236099Sdes printf("\t.module = &%s_pam_module,\n", modname); 107236099Sdes printf("\t.flag = 0x%08x,\n", chain->flag); 108236099Sdes printf("\t.optc = %d,\n", chain->optc); 109236099Sdes printf("\t.optv = %s_%d_optv,\n", name, i); 110236099Sdes if (chain->next) 111236099Sdes printf("\t.next = &%s_%d,\n", name, i + 1); 112236099Sdes else 113236099Sdes printf("\t.next = NULL,\n"); 114236099Sdes printf("};\n"); 115236099Sdes free(modname); 116236099Sdes } 117236099Sdes return (PAM_SUCCESS); 118236099Sdes} 119236099Sdes 120236099Sdesint 121236099Sdesopenpam_dump_policy(const char *service) 122236099Sdes{ 123236099Sdes pam_handle_t *pamh; 124236099Sdes char *name; 125236099Sdes int fclt, ret; 126236099Sdes 127236099Sdes if ((pamh = calloc(1, sizeof *pamh)) == NULL) 128236099Sdes return (PAM_BUF_ERR); 129236099Sdes if ((ret = openpam_configure(pamh, service)) != PAM_SUCCESS) 130236099Sdes return (ret); 131236099Sdes for (fclt = 0; fclt < PAM_NUM_FACILITIES; ++fclt) { 132236099Sdes if (pamh->chains[fclt] != NULL) { 133236099Sdes if ((name = openpam_chain_name(service, fclt)) == NULL) 134236099Sdes return (PAM_BUF_ERR); 135236099Sdes ret = openpam_dump_chain(name, pamh->chains[fclt]); 136236099Sdes free(name); 137236099Sdes if (ret != PAM_SUCCESS) 138236099Sdes return (ret); 139236099Sdes } 140236099Sdes } 141236099Sdes printf("static pam_policy_t pam_%s_policy = {\n", service); 142236099Sdes printf("\t.service = \"%s\",\n", service); 143236099Sdes printf("\t.chains = {\n"); 144236099Sdes for (fclt = 0; fclt < PAM_NUM_FACILITIES; ++fclt) { 145236099Sdes if ((name = openpam_facility_index_name(fclt)) == NULL) 146236099Sdes return (PAM_BUF_ERR); 147236099Sdes printf("\t\t[%s] = ", name); 148236099Sdes free(name); 149236099Sdes if (pamh->chains[fclt] != NULL) { 150236099Sdes if ((name = openpam_chain_name(service, fclt)) == NULL) 151236099Sdes return (PAM_BUF_ERR); 152236099Sdes printf("&%s_0,\n", name); 153236099Sdes free(name); 154236099Sdes } else { 155236099Sdes printf("NULL,\n"); 156236099Sdes } 157236099Sdes } 158236099Sdes printf("\t},\n"); 159236099Sdes printf("};\n"); 160236099Sdes free(pamh); 161236099Sdes return (PAM_SUCCESS); 162236099Sdes} 163236099Sdes 164236099Sdesstatic void 165236099Sdesusage(void) 166236099Sdes{ 167236099Sdes 168236099Sdes fprintf(stderr, "usage: openpam_dump_policy [-d] policy ...\n"); 169236099Sdes exit(1); 170236099Sdes} 171236099Sdes 172236099Sdesint 173236099Sdesmain(int argc, char *argv[]) 174236099Sdes{ 175236099Sdes int i, opt; 176236099Sdes 177236099Sdes while ((opt = getopt(argc, argv, "d")) != -1) 178236099Sdes switch (opt) { 179236099Sdes case 'd': 180236099Sdes openpam_debug = 1; 181236099Sdes break; 182236099Sdes default: 183236099Sdes usage(); 184236099Sdes } 185236099Sdes 186236099Sdes argc -= optind; 187236099Sdes argv += optind; 188236099Sdes 189236099Sdes if (argc < 1) 190236099Sdes usage(); 191236099Sdes 192236099Sdes printf("#include <security/pam_appl.h>\n"); 193236099Sdes printf("#include \"openpam_impl.h\"\n"); 194236099Sdes for (i = 0; i < argc; ++i) 195236099Sdes openpam_dump_policy(argv[i]); 196236099Sdes printf("pam_policy_t *pam_embedded_policies[] = {\n"); 197236099Sdes for (i = 0; i < argc; ++i) 198236099Sdes printf("\t&pam_%s_policy,\n", argv[i]); 199236099Sdes printf("\tNULL,\n"); 200236099Sdes printf("};\n"); 201236099Sdes exit(0); 202236099Sdes} 203