1 /* $NetBSD: pt_filter.c,v 1.4 2001/01/10 03:33:16 lukem Exp $ */ 2 3 /* 4 * Copyright (c) 1999 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD 8 * Foundation by Brian Grayson, and is dedicated to Rebecca 9 * Margaret Pollard-Grayson. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 #include <sys/cdefs.h> 41 #ifndef lint 42 __RCSID("$NetBSD: pt_filter.c,v 1.4 2001/01/10 03:33:16 lukem Exp $"); 43 #endif /* not lint */ 44 45 #include <stdio.h> 46 #include <unistd.h> 47 #include <stdlib.h> 48 #include <errno.h> 49 #include <string.h> 50 #include <sys/types.h> 51 #include <sys/param.h> 52 #include <sys/syslog.h> 53 54 #include "portald.h" 55 56 /* 57 * Key will be <key><path>. We let the configuration file 58 * tell us how to filter the file. 59 */ 60 61 #define FILTER_CMD_SIZE 8192 62 63 static void fill_cmd __P((char **, char *, char *, int)); 64 65 static void 66 fill_cmd(cmdv, path, buff, n) 67 char **cmdv; 68 char *path; 69 char *buff; 70 int n; 71 { 72 int i; 73 /* Make tempbuff at least as large as buff. */ 74 char tempbuff[n]; 75 76 strncpy(tempbuff, cmdv[0], n); 77 for (i = 1; cmdv[i]; i++) { 78 strncat(tempbuff, " ", n - strlen(tempbuff)); 79 strncat(tempbuff, cmdv[i], n - strlen(tempbuff)); 80 } 81 strncat(tempbuff, " ", n - strlen(tempbuff)); 82 /* Now do the snprintf into buff. */ 83 snprintf(buff, n, tempbuff, path); 84 } 85 86 87 /* 88 * Strip v[1], replace %s in v[2] v[3] ... with the remainder 89 * of the path, and exec v[2] v[3] ... on the remainder. 90 */ 91 int 92 portal_rfilter(pcr, key, v, kso, fdp) 93 struct portal_cred *pcr; 94 char *key; 95 char **v; 96 int kso; 97 int *fdp; 98 { 99 char cmd[FILTER_CMD_SIZE]; 100 char *path; 101 FILE *fp; 102 int error = 0; 103 104 /* We don't use this parameter. */ 105 (void) kso; 106 107 error = lose_credentials(pcr); 108 if (error != 0) 109 return error; 110 111 #ifdef DEBUG 112 fprintf(stderr, "rfilter: Got key %s\n", key); 113 #endif 114 115 errno = 0; 116 if (!v[1] || !v[2]) { 117 syslog(LOG_ERR, 118 "rfilter: got strip-key of %s, and command start of %s\n", 119 v[1], v[2]); 120 exit(1); 121 } 122 /* 123 * Format for rfilter in config file: 124 * 125 * matchkey rfilter stripkey cmd [arg1] [arg2] ... 126 * any of arg1, arg2, etc. can have %s, in which case %s 127 * will be replaced by the full path. If arg1 is 128 * missing, %s is assumed, i.e. 129 * bogus1 rfilter bogus1/ cmd1 130 * is equivalent to 131 * bogus1 rfilter bogus1/ cmd1 %s 132 */ 133 /* 134 * v[3] could be NULL, or could point to "". 135 */ 136 if (!v[3] || strlen(v[3]) == 0) 137 v[3] = "%s"; /* Handle above assumption. */ 138 path = key; 139 /* Strip out stripkey if it matches leading part of key. */ 140 if (!strncmp(v[1], key, strlen(v[1]))) 141 path += strlen(v[1]); 142 /* 143 * v[0] is key match, v[1] says how much to strip, v[2] 144 * is beginning of command proper. The first %s in v[2] 145 * ... will be replaced with the path. 146 */ 147 fill_cmd(v + 2, path, cmd, FILTER_CMD_SIZE); 148 if (strlen(cmd) >= FILTER_CMD_SIZE) { 149 syslog(LOG_WARNING, 150 "Warning: potential overflow on string! Length was %lu\n", 151 (unsigned long)strlen(cmd)); 152 return -1; 153 } 154 #ifdef DEBUG 155 fprintf(stderr, "rfilter: Using cmd of %s\n", cmd); 156 #endif 157 fp = popen(cmd, "r"); 158 if (fp == NULL) { 159 return errno; 160 } 161 162 /* Before returning, restore original uid and gid. */ 163 /* But only do this if we were root to start with. */ 164 if (getuid() == 0) { 165 if ((seteuid((uid_t) 0) < 0) || (setegid((gid_t) 0) < 0)) { 166 error = errno; 167 syslog(LOG_WARNING, "setcred: %m"); 168 if (fp) { 169 fclose(fp); 170 fp = NULL; 171 } 172 } 173 } 174 if (error == 0) 175 fdp[0] = fileno(fp); 176 return (errno); 177 } 178 179 int 180 portal_wfilter(pcr, key, v, kso, fdp) 181 struct portal_cred *pcr; 182 char *key; 183 char **v; 184 int kso; 185 int *fdp; 186 { 187 char cmd[FILTER_CMD_SIZE]; 188 char *path; 189 FILE *fp; 190 int error = 0; 191 int cred_change_err = 0; 192 193 /* We don't use this parameter. */ 194 (void) kso; 195 196 cred_change_err = lose_credentials(pcr); 197 if (cred_change_err != 0) 198 return cred_change_err; 199 200 errno = 0; 201 path = key + (v[1] ? strlen(v[1]) : 0); 202 /* 203 * v[0] is key match, v[1] says how much to strip, v[2] 204 * is beginning of command proper. 205 */ 206 fill_cmd(v + 2, path, cmd, FILTER_CMD_SIZE); 207 if (strlen(cmd) >= FILTER_CMD_SIZE) { 208 syslog(LOG_WARNING, 209 "Warning: potential overflow on string! Length was %lu\n", 210 (unsigned long)strlen(cmd)); 211 return -1; 212 } 213 fp = popen(cmd, "w"); 214 if (fp == NULL) { 215 return errno; 216 } 217 /* Before returning, restore original uid and gid. */ 218 /* But only do this if we were root to start with. */ 219 if (getuid() == 0) { 220 if ((seteuid((uid_t) 0) < 0) || (setegid((gid_t) 0) < 0)) { 221 error = errno; 222 syslog(LOG_WARNING, "setcred: %m"); 223 if (fp) { 224 fclose(fp); 225 fp = NULL; 226 } 227 } 228 } 229 if (error == 0) 230 fdp[0] = fileno(fp); 231 return (errno); 232 } 233