config.c
1 /* 2 * Copyright (c) 2005, PADL Software Pty Ltd. 3 * All rights reserved. 4 * 5 * Portions Copyright (c) 2009 Apple Inc. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * 3. Neither the name of PADL Software nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include "kcm_locl.h" 36 #include <getarg.h> 37 38 static void usage(int ret) __attribute__((noreturn)); 39 40 static const char *config_file; /* location of kcm config file */ 41 42 size_t max_request = 0; /* maximal size of a request */ 43 char *socket_path = NULL; 44 char *door_path = NULL; 45 46 static char *max_request_str; /* `max_request' as a string */ 47 48 #ifdef SUPPORT_DETACH 49 int detach_from_console = -1; 50 #define DETACH_IS_DEFAULT FALSE 51 #endif 52 53 static const char *system_cache_name = NULL; 54 static const char *system_keytab = NULL; 55 static const char *system_principal = NULL; 56 static const char *system_server = NULL; 57 static const char *system_user = NULL; 58 static const char *system_group = NULL; 59 60 static const char *renew_life = NULL; 61 static const char *ticket_life = NULL; 62 63 int launchd_flag = 0; 64 int disallow_getting_krbtgt = 0; 65 int use_uid_matching = -1; 66 int disable_ntlm_reflection_detection = 0; 67 int max_num_requests = 100000; 68 int kcm_timeout = -1; 69 70 static int help_flag; 71 static int version_flag; 72 73 static struct getargs args[] = { 74 { 75 "cache-name", 0, arg_string, &system_cache_name, 76 "system cache name", "cachename" 77 }, 78 { 79 "config-file", 'c', arg_string, &config_file, 80 "location of config file", "file" 81 }, 82 { 83 "group", 'g', arg_string, &system_group, 84 "system cache group", "group" 85 }, 86 { 87 "max-request", 0, arg_string, &max_request, 88 "max size for a kcm-request", "size" 89 }, 90 { 91 "launchd", 0, arg_flag, &launchd_flag, 92 "when in use by launchd" 93 }, 94 #ifdef SUPPORT_DETACH 95 #if DETACH_IS_DEFAULT 96 { 97 "detach", 'D', arg_negative_flag, &detach_from_console, 98 "don't detach from console" 99 }, 100 #else 101 { 102 "detach", 0 , arg_flag, &detach_from_console, 103 "detach from console" 104 }, 105 #endif 106 #endif 107 { "help", 'h', arg_flag, &help_flag }, 108 { 109 "system-principal", 'k', arg_string, &system_principal, 110 "system principal name", "principal" 111 }, 112 { 113 "lifetime", 'l', arg_string, &ticket_life, 114 "lifetime of system tickets", "time" 115 }, 116 { 117 "disallow-getting-krbtgt", 0, arg_flag, &disallow_getting_krbtgt, 118 "disable fetching krbtgt from the cache" 119 }, 120 { 121 "use-uid-matching", 0, arg_flag, &use_uid_matching, 122 "only use UID when matching allowed credentials or not" 123 }, 124 { 125 "renewable-life", 'r', arg_string, &renew_life, 126 "renewable lifetime of system tickets", "time" 127 }, 128 { 129 "socket-path", 's', arg_string, &socket_path, 130 "path to kcm domain socket", "path" 131 }, 132 #ifdef HAVE_DOOR_CREATE 133 { 134 "door-path", 's', arg_string, &door_path, 135 "path to kcm door", "path" 136 }, 137 #endif 138 { 139 "server", 'S', arg_string, &system_server, 140 "server to get system ticket for", "principal" 141 }, 142 { 143 "keytab", 't', arg_string, &system_keytab, 144 "system keytab name", "keytab" 145 }, 146 { 147 "user", 'u', arg_string, &system_user, 148 "system cache owner", "user" 149 }, 150 { 151 "number-requests", 0, arg_integer, &max_num_requests, 152 "number of requests processed before exit" 153 }, 154 { 155 "idle-timeout", 0, arg_integer, &kcm_timeout, 156 "number of seconds of idle time before timeout (0 disables timeout)", "seconds" 157 }, 158 { "version", 'v', arg_flag, &version_flag } 159 }; 160 161 static int num_args = sizeof(args) / sizeof(args[0]); 162 163 static void 164 usage(int ret) 165 { 166 arg_printusage (args, num_args, NULL, ""); 167 exit (ret); 168 } 169 170 static int parse_owners(kcm_ccache ccache) 171 { 172 uid_t uid = 0; 173 struct passwd *pw; 174 int uid_p = 0; 175 176 if (system_user != NULL) { 177 if (isdigit((unsigned char)system_user[0])) { 178 pw = getpwuid(atoi(system_user)); 179 } else { 180 pw = getpwnam(system_user); 181 } 182 if (pw == NULL) { 183 return errno; 184 } 185 186 system_user = strdup(pw->pw_name); 187 if (system_user == NULL) { 188 return ENOMEM; 189 } 190 191 uid = pw->pw_uid; uid_p = 1; 192 } 193 194 if (uid_p) 195 ccache->uid = uid; 196 else 197 ccache->uid = 0; /* geteuid() XXX */ 198 199 return 0; 200 } 201 202 static const char * 203 kcm_system_config_get_string(const char *string) 204 { 205 return krb5_config_get_string(kcm_context, NULL, "kcm", 206 "system_ccache", string, NULL); 207 } 208 209 static krb5_error_code 210 ccache_init_system(void) 211 { 212 kcm_ccache ccache; 213 krb5_error_code ret; 214 215 if (system_cache_name == NULL) 216 system_cache_name = kcm_system_config_get_string("cc_name"); 217 218 ret = kcm_ccache_new(kcm_context, 219 system_cache_name ? system_cache_name : "SYSTEM", 220 &ccache); 221 if (ret) 222 return ret; 223 224 ccache->flags |= KCM_FLAGS_OWNER_IS_SYSTEM; 225 ccache->flags |= KCM_FLAGS_USE_KEYTAB; 226 227 ret = parse_owners(ccache); 228 if (ret) 229 return ret; 230 231 ret = krb5_parse_name(kcm_context, system_principal, &ccache->client); 232 if (ret) { 233 kcm_release_ccache(kcm_context, ccache); 234 return ret; 235 } 236 237 if (system_server == NULL) 238 system_server = kcm_system_config_get_string("server"); 239 240 if (system_server != NULL) { 241 ret = krb5_parse_name(kcm_context, system_server, &ccache->server); 242 if (ret) { 243 kcm_release_ccache(kcm_context, ccache); 244 return ret; 245 } 246 } 247 248 if (system_keytab == NULL) 249 system_keytab = kcm_system_config_get_string("keytab_name"); 250 251 if (system_keytab != NULL) { 252 ret = krb5_kt_resolve(kcm_context, system_keytab, &ccache->keytab); 253 } else { 254 ret = krb5_kt_default(kcm_context, &ccache->keytab); 255 } 256 if (ret) { 257 kcm_release_ccache(kcm_context, ccache); 258 return ret; 259 } 260 261 if (renew_life == NULL) 262 renew_life = kcm_system_config_get_string("renew_life"); 263 264 if (renew_life == NULL) 265 renew_life = "1 month"; 266 267 if (renew_life != NULL) { 268 ccache->renew_life = parse_time(renew_life, "s"); 269 if (ccache->renew_life < 0) { 270 kcm_release_ccache(kcm_context, ccache); 271 return EINVAL; 272 } 273 } 274 275 if (ticket_life == NULL) 276 ticket_life = kcm_system_config_get_string("ticket_life"); 277 278 if (ticket_life != NULL) { 279 ccache->tkt_life = parse_time(ticket_life, "s"); 280 if (ccache->tkt_life < 0) { 281 kcm_release_ccache(kcm_context, ccache); 282 return EINVAL; 283 } 284 } 285 286 /* enqueue default actions for credentials cache */ 287 ret = kcm_ccache_enqueue_default(kcm_context, ccache, NULL); 288 289 kcm_release_ccache(kcm_context, ccache); /* retained by event queue */ 290 291 return ret; 292 } 293 294 void 295 kcm_configure(int argc, char **argv) 296 { 297 krb5_error_code ret; 298 int optidx = 0; 299 const char *p; 300 301 while(getarg(args, num_args, argc, argv, &optidx)) 302 warnx("error at argument `%s'", argv[optidx]); 303 304 if(help_flag) 305 usage (0); 306 307 if (version_flag) { 308 print_version(NULL); 309 exit(0); 310 } 311 312 argc -= optidx; 313 314 if (argc != 0) 315 usage(1); 316 317 { 318 char **files; 319 320 if(config_file == NULL) 321 config_file = _PATH_KCM_CONF; 322 323 ret = krb5_prepend_config_files_default(config_file, &files); 324 if (ret) 325 krb5_err(kcm_context, 1, ret, "getting configuration files"); 326 327 ret = krb5_set_config_files(kcm_context, files); 328 krb5_free_config_files(files); 329 if(ret) 330 krb5_err(kcm_context, 1, ret, "reading configuration files"); 331 } 332 333 if(max_request_str) 334 max_request = parse_bytes(max_request_str, NULL); 335 336 if(max_request == 0){ 337 p = krb5_config_get_string (kcm_context, 338 NULL, 339 "kcm", 340 "max-request", 341 NULL); 342 if(p) 343 max_request = parse_bytes(p, NULL); 344 } 345 346 if (system_principal == NULL) { 347 system_principal = kcm_system_config_get_string("principal"); 348 } 349 350 if (system_principal != NULL) { 351 ret = ccache_init_system(); 352 if (ret) 353 krb5_err(kcm_context, 1, ret, "initializing system ccache"); 354 } 355 356 if (disallow_getting_krbtgt == -1) { 357 disallow_getting_krbtgt = 358 krb5_config_get_bool_default(kcm_context, NULL, FALSE, "kcm", 359 "disallow-getting-krbtgt", NULL); 360 } 361 362 #ifdef SUPPORT_DETACH 363 if(detach_from_console == -1) 364 detach_from_console = krb5_config_get_bool_default(kcm_context, NULL, 365 DETACH_IS_DEFAULT, 366 "kcm", 367 "detach", NULL); 368 #endif 369 370 if (use_uid_matching == -1) 371 use_uid_matching = krb5_config_get_bool_default(kcm_context, NULL, 372 0, 373 "kcm", 374 "use-uid-matching", NULL); 375 376 disable_ntlm_reflection_detection = krb5_config_get_bool_default(kcm_context, NULL, 377 0, 378 "kcm", 379 "disable-ntlm-reflection-detection", NULL); 380 381 kcm_openlog(); 382 if(max_request == 0) 383 max_request = 64 * 1024; 384 } 385