/ kcm / config.c
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