1 /* cfg.h --- Configuration file functions.
2 * Copyright (C) 2002, 2003, 2004, 2006, 2007 Simon Josefsson
4 * This file is part of Shishi.
6 * Shishi is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * Shishi is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Shishi; if not, see http://www.gnu.org/licenses or write
18 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
19 * Floor, Boston, MA 02110-1301, USA
28 #define KDC_SERVICE_PORT "\x6b\x65\x72\x62\x65\x72\x6f\x73"
32 DEFAULT_REALM_OPTION
= 0,
33 DEFAULT_PRINCIPAL_OPTION
,
34 CLIENT_KDC_ETYPES_OPTION
,
41 AUTHORIZATION_TYPES_OPTION
,
42 VERBOSE_CRYPTO_NOISE_OPTION
,
43 VERBOSE_CRYPTO_OPTION
,
51 static const char *_shishi_opts
[] = {
52 /* [DEFAULT_REALM_OPTION] = */ "default-realm",
53 /* [DEFAULT_PRINCIPAL_OPTION] = */ "default-principal",
54 /* [CLIENT_KDC_ETYPES_OPTION] = */ "client-kdc-etypes",
55 /* [REALM_KDC_OPTION] = */ "realm-kdc",
56 /* [SERVER_REALM_OPTION] = */ "server-realm",
57 /* [KDC_TIMEOUT_OPTION] = */ "kdc-timeout",
58 /* [KDC_RETRIES_OPTION] = */ "kdc-retries",
59 /* [TICKET_LIFE_OPTION] = */ "ticket-life",
60 /* [RENEW_LIFE_OPTION] = */ "renew-life",
61 /* [AUTHORIZATION_TYPES_OPTION] = */ "authorization-types",
62 /* [VERBOSE_CRYPTO_NOISE_OPTION] = */ "verbose-crypto-noise",
63 /* [VERBOSE_CRYPTO_OPTION] = */ "verbose-crypto",
64 /* [VERBOSE_ASN1_OPTION] = */ "verbose-asn1",
65 /* [VERBOSE_NOISE_OPTION] = */ "verbose-noise",
66 /* [VERBOSE_OPTION] = */ "verbose",
67 /* [STRINGPROCESS_OPTION] = */ "stringprocess",
68 /* [THE_END] = */ NULL
71 struct Shishi_realminfo
*
72 _shishi_realminfo (Shishi
* handle
, const char *realm
)
76 for (i
= 0; i
< handle
->nrealminfos
; i
++)
77 if (strcmp (realm
, handle
->realminfos
[i
].name
) == 0)
78 return &handle
->realminfos
[i
];
83 struct Shishi_realminfo
*
84 _shishi_realminfo_new (Shishi
* handle
, char *realm
)
86 struct Shishi_realminfo
*ri
;
88 ri
= _shishi_realminfo (handle
, realm
);
92 handle
->realminfos
= xrealloc (handle
->realminfos
,
93 (++handle
->nrealminfos
) *
94 sizeof (*handle
->realminfos
));
96 ri
= &handle
->realminfos
[handle
->nrealminfos
- 1];
97 memset (ri
, 0, sizeof (*ri
));
105 * @handle: Shishi library handle create by shishi_init().
106 * @option: string with shishi library option.
108 * Configure shishi library with given option.
110 * Return Value: Returns SHISHI_OK if option was valid.
113 shishi_cfg (Shishi
* handle
, char *option
)
120 while (option
!= NULL
&& *option
!= '\0')
122 switch (getsubopt (&option
, _shishi_opts
, &value
))
124 case KDC_TIMEOUT_OPTION
:
125 if (value
&& atoi (value
) > 0)
126 handle
->kdctimeout
= atoi (value
);
128 shishi_warn (handle
, "Invalid KDC timeout value: `%s'", value
);
130 shishi_warn (handle
, "Missing KDC timeout value");
133 case KDC_RETRIES_OPTION
:
134 if (value
&& atoi (value
) > 0)
135 handle
->kdcretries
= atoi (value
);
137 shishi_warn (handle
, "Invalid KDC retries value: `%s'", value
);
139 shishi_warn (handle
, "Missing KDC retries value");
142 case TICKET_LIFE_OPTION
:
144 time_t now
= time (NULL
);
145 time_t then
= shishi_get_date (value
, &now
);
146 int diff
= difftime (then
, now
);
148 if (value
&& then
!= -1 && diff
> 0)
149 handle
->ticketlife
= diff
;
150 else if (diff
<= 0 && diff
+ 60 * 60 * 24 > 0)
151 /* Hack to support "17:00" as always meaning the next 17:00. */
152 handle
->ticketlife
= 60 * 60 * 24 + diff
;
154 shishi_warn (handle
, "Negative ticket life date: `%s'", value
);
156 shishi_warn (handle
, "Invalid ticket life date: `%s'", value
);
158 shishi_warn (handle
, "Missing ticket life value");
162 case RENEW_LIFE_OPTION
:
164 time_t now
= time (NULL
);
165 time_t then
= shishi_get_date (value
, &now
);
166 int diff
= difftime (then
, now
);
168 if (value
&& then
!= -1 && diff
> 0)
169 handle
->renewlife
= diff
;
171 shishi_warn (handle
, "Negative renew life date: `%s'", value
);
173 shishi_warn (handle
, "Invalid renew life date: `%s'", value
);
175 shishi_warn (handle
, "Missing renew life value");
179 case REALM_KDC_OPTION
:
180 realm
= xstrdup (value
);
181 for (i
= 0; i
< handle
->nrealminfos
; i
++)
182 if (strcmp (realm
, handle
->realminfos
[i
].name
) == 0)
184 if (handle
->realminfos
[i
].nkdcaddresses
> 0 ||
185 handle
->realminfos
[i
].kdcaddresses
)
187 if (handle
->realminfos
[i
].kdcaddresses
)
188 free (handle
->realminfos
[i
].kdcaddresses
);
189 handle
->realminfos
[i
].kdcaddresses
= NULL
;
190 handle
->realminfos
[i
].nkdcaddresses
= 0;
194 handle
->realminfos
= xrealloc (handle
->realminfos
,
195 (handle
->nrealminfos
+ 1) *
196 sizeof (*handle
->realminfos
));
197 memset (&handle
->realminfos
[handle
->nrealminfos
], 0,
198 sizeof (handle
->realminfos
[handle
->nrealminfos
]));
199 handle
->realminfos
[handle
->nrealminfos
].name
= realm
;
200 handle
->nrealminfos
++;
203 case SERVER_REALM_OPTION
:
205 struct Shishi_realminfo
*ri
;
206 ri
= _shishi_realminfo_new (handle
, value
);
207 ri
->serverwildcards
= xrealloc (ri
->serverwildcards
,
208 ++ri
->nserverwildcards
*
209 sizeof (*ri
->serverwildcards
));
210 ri
->serverwildcards
[ri
->nserverwildcards
- 1] = xstrdup (value
);
214 case DEFAULT_REALM_OPTION
:
215 handle
->default_realm
= xstrdup (value
);
218 case DEFAULT_PRINCIPAL_OPTION
:
219 handle
->default_principal
= xstrdup (value
);
222 case CLIENT_KDC_ETYPES_OPTION
:
223 res
= shishi_cfg_clientkdcetype_set (handle
, value
);
224 if (res
!= SHISHI_OK
)
228 case AUTHORIZATION_TYPES_OPTION
:
229 res
= shishi_cfg_authorizationtype_set (handle
, value
);
230 if (res
!= SHISHI_OK
)
234 case STRINGPROCESS_OPTION
:
235 if (handle
->stringprocess
)
236 free (handle
->stringprocess
);
237 handle
->stringprocess
= xstrdup (value
);
241 handle
->verbose
= value
&& atoi (value
) ? atoi (value
) :
245 case VERBOSE_CRYPTO_NOISE_OPTION
:
246 handle
->verbose
|= SHISHI_VERBOSE_CRYPTO_NOISE
;
249 case VERBOSE_CRYPTO_OPTION
:
250 handle
->verbose
|= SHISHI_VERBOSE_CRYPTO
;
253 case VERBOSE_ASN1_OPTION
:
254 handle
->verbose
|= SHISHI_VERBOSE_ASN1
;
257 case VERBOSE_NOISE_OPTION
:
258 handle
->verbose
|= SHISHI_VERBOSE_NOISE
;
264 for (i
= 0; i
< handle
->nrealminfos
; i
++)
265 if (realm
&& handle
->realminfos
[i
].name
== realm
)
267 struct Shishi_realminfo
*ri
= &handle
->realminfos
[i
];
268 struct sockaddr_in
*sinaddr
;
275 if ((p
= strchr (value
, '/')))
279 if (strcasecmp (p
, "udp") == 0)
281 else if (strcasecmp (p
, "tcp") == 0)
283 else if (strcasecmp (p
, "tls") == 0)
287 "Ignoring unknown KDC parameter: %s", p
);
290 if ((p
= strchr (value
, ':')))
297 he
= gethostbyname (value
); /* XXX move to netio.c */
299 he
->h_addr_list
[0] == NULL
|| he
->h_addrtype
!= AF_INET
)
302 "Unknown KDC host `%s' (h_errno %d)",
307 ri
->kdcaddresses
= xrealloc (ri
->kdcaddresses
,
308 (ri
->nkdcaddresses
+ 1) *
309 sizeof (*ri
->kdcaddresses
));
310 ri
->kdcaddresses
[ri
->nkdcaddresses
].name
= xstrdup (value
);
311 ri
->kdcaddresses
[ri
->nkdcaddresses
].protocol
= protocol
;
312 sinaddr
= (struct sockaddr_in
*)
313 &ri
->kdcaddresses
[ri
->nkdcaddresses
].sockaddress
;
314 memset (sinaddr
, 0, sizeof (struct sockaddr
));
317 sinaddr
->sin_family
= he
->h_addrtype
;
318 memcpy (&sinaddr
->sin_addr
, he
->h_addr_list
[0], he
->h_length
);
321 se
= getservbyname (KDC_SERVICE_PORT
, NULL
);
323 sinaddr
->sin_port
= se
->s_port
;
325 sinaddr
->sin_port
= htons (88);
328 sinaddr
->sin_port
= htons (port
);
335 shishi_warn (handle
, "Unknown option: `%s'", value
);
344 * shishi_cfg_from_file:
345 * @handle: Shishi library handle create by shishi_init().
346 * @cfg: filename to read configuration from.
348 * Configure shishi library using configuration file.
350 * Return Value: Returns SHISHI_OK iff succesful.
353 shishi_cfg_from_file (Shishi
* handle
, const char *cfg
)
362 fh
= fopen (cfg
, "r");
365 shishi_warn (handle
, "`%s': %s", cfg
, strerror (errno
));
366 return SHISHI_FOPEN_ERROR
;
371 ssize_t n
= getline (&line
, &len
, fh
);
376 /* End of file or error. */
379 while (strlen (p
) > 0 && (p
[strlen (p
) - 1] == '\n' ||
380 p
[strlen (p
) - 1] == '\r'))
381 p
[strlen (p
) - 1] = '\0';
383 while (*p
&& strchr (" \t\r\n", *p
))
386 if (*p
== '\0' || *p
== '#')
390 if (q
&& (strchr (p
, '=') == NULL
|| q
< strchr (p
, '=')))
393 shishi_cfg (handle
, p
);
400 shishi_error_printf (handle
, "Error reading configuration file");
402 if (fclose (fh
) != 0)
403 return SHISHI_IO_ERROR
;
410 * @handle: Shishi library handle create by shishi_init().
411 * @fh: file descriptor opened for writing.
413 * Print library configuration status, mostly for debugging purposes.
415 * Return Value: Returns SHISHI_OK.
418 shishi_cfg_print (Shishi
* handle
, FILE * fh
)
421 time_t tmp
, now
= time (NULL
);
423 fprintf (fh
, "Shishi initial library configuration:\n");
424 fprintf (fh
, "\tDefault realm: %s\n",
425 handle
->default_realm
? handle
->default_realm
: "(NULL)");
426 fprintf (fh
, "\tDefault principal: %s\n",
427 handle
->default_principal
? handle
->default_principal
: "(NULL)");
428 fprintf (fh
, "\tClient KDC etypes:");
429 for (i
= 0; i
< handle
->nclientkdcetypes
; i
++)
430 fprintf (fh
, " %s", shishi_cipher_name (handle
->clientkdcetypes
[i
]));
432 fprintf (fh
, "\tKDC: %s\n", handle
->kdc
? handle
->kdc
: "(NULL)");
433 fprintf (fh
, "\tVerbose: %d\n", handle
->verbose
);
434 tmp
= now
+ handle
->ticketlife
;
435 fprintf (fh
, "\tTicket life: %d seconds. %s",
436 handle
->ticketlife
, ctime (&tmp
));
437 tmp
= now
+ handle
->renewlife
;
438 fprintf (fh
, "\tRenew life: %d seconds. %s",
439 handle
->renewlife
, ctime (&tmp
));
440 for (i
= 0; i
< handle
->nrealminfos
; i
++)
442 fprintf (fh
, "\tRealm %s's KDCs:", handle
->realminfos
[i
].name
);
443 for (j
= 0; j
< handle
->realminfos
[i
].nkdcaddresses
; j
++)
444 fprintf (fh
, " %s (%s)", handle
->realminfos
[i
].kdcaddresses
[j
].name
,
445 inet_ntoa (((struct sockaddr_in
*) &handle
->realminfos
[i
].
446 kdcaddresses
[j
].sockaddress
)->sin_addr
));
454 * shishi_cfg_default_systemfile:
455 * @handle: Shishi library handle create by shishi_init().
457 * The system configuration file name is decided at compile-time, but
458 * may be overridden by the environment variable SHISHI_CONFIG.
460 * Return value: Return system configuration file name.
463 shishi_cfg_default_systemfile (Shishi
* handle
)
467 file
= getenv ("SHISHI_CONFIG");
471 return SYSTEMCFGFILE
;
474 #define BASE_DIR "/.shishi"
477 * shishi_cfg_default_userdirectory:
478 * @handle: Shishi library handle create by shishi_init().
480 * The default user directory (used for, e.g. Shishi ticket cache) is
481 * normally computed by appending BASE_DIR ("/.shishi") to the content
482 * of the environment variable $HOME, but can be overridden by
483 * specifying the complete path in the environment variable
486 * Return value: Return directory with configuration files etc.
489 shishi_cfg_default_userdirectory (Shishi
* handle
)
494 envdir
= getenv ("SHISHI_HOME");
498 if (!handle
->userdirectory
)
500 home
= getenv ("HOME");
502 asprintf (&handle
->userdirectory
, "%s%s", home
? home
: "", BASE_DIR
);
505 return handle
->userdirectory
;
509 * shishi_cfg_userdirectory_file:
510 * @handle: Shishi library handle create by shishi_init().
511 * @file: basename of file to find in user directory.
513 * Get the full path to specified @file in the users' configuration
516 * Return value: Return full path to given relative filename, relative
517 * to the user specific Shishi configuration directory as returned
518 * by shishi_cfg_default_userdirectory() (typically $HOME/.shishi).
521 shishi_cfg_userdirectory_file (Shishi
* handle
, const char *file
)
525 asprintf (&out
, "%s/%s", shishi_cfg_default_userdirectory (handle
), file
);
530 #define USERCFG_FILE "shishi.conf"
533 * shishi_cfg_default_userfile:
534 * @handle: Shishi library handle create by shishi_init().
536 * Get filename of default user configuration file, typically
539 * Return value: Return user configuration filename.
542 shishi_cfg_default_userfile (Shishi
* handle
)
544 if (!handle
->usercfgfile
)
545 handle
->usercfgfile
=
546 shishi_cfg_userdirectory_file (handle
, USERCFG_FILE
);
548 return handle
->usercfgfile
;
552 * shishi_cfg_clientkdcetype:
553 * @handle: Shishi library handle create by shishi_init().
554 * @etypes: output array with encryption types.
556 * Set the etypes variable to the array of preferred client etypes.
558 * Return value: Return the number of encryption types in the array,
562 shishi_cfg_clientkdcetype (Shishi
* handle
, int32_t ** etypes
)
564 *etypes
= handle
->clientkdcetypes
;
565 return handle
->nclientkdcetypes
;
569 * shishi_cfg_clientkdcetype_fast:
570 * @handle: Shishi library handle create by shishi_init().
572 * Extract the default etype from the list of preferred client etypes.
574 * Return value: Return the default encryption types.
577 shishi_cfg_clientkdcetype_fast (Shishi
* handle
)
579 if (handle
->nclientkdcetypes
> 0)
580 return handle
->clientkdcetypes
[0];
582 return SHISHI_AES256_CTS_HMAC_SHA1_96
;
586 * shishi_cfg_clientkdcetype_set:
587 * @handle: Shishi library handle create by shishi_init().
588 * @value: string with encryption types.
590 * Set the "client-kdc-etypes" configuration option from given string.
591 * The string contains encryption types (integer or names) separated
592 * by comma or whitespace, e.g. "aes256-cts-hmac-sha1-96
593 * des3-cbc-sha1-kd des-cbc-md5".
595 * Return value: Return SHISHI_OK iff successful.
598 shishi_cfg_clientkdcetype_set (Shishi
* handle
, char *value
)
605 if (value
== NULL
|| *value
== '\0')
608 for (i
= 0; (val
= strtok_r (i
== 0 ? value
: NULL
, ", \t", &ptrptr
)); i
++)
610 int etype
= shishi_cipher_parse (val
);
613 shishi_warn (handle
, "Ignoring unknown encryption type: `%s'", val
);
619 new = xrealloc (handle
->clientkdcetypes
,
620 tot
* sizeof (*handle
->clientkdcetypes
));
621 handle
->clientkdcetypes
= new;
622 handle
->clientkdcetypes
[tot
- 1] = etype
;
623 handle
->nclientkdcetypes
= tot
;
631 * shishi_cfg_authorizationtype_set:
632 * @handle: Shishi library handle create by shishi_init().
633 * @value: string with authorization types.
635 * Set the "authorization-types" configuration option from given string.
636 * The string contains authorization types (integer or names) separated
637 * by comma or whitespace, e.g. "basic k5login".
639 * Return value: Return SHISHI_OK iff successful.
642 shishi_cfg_authorizationtype_set (Shishi
* handle
, char *value
)
649 if (value
== NULL
|| *value
== '\0')
652 for (i
= 0; (val
= strtok_r (i
== 0 ? value
: NULL
, ", \t", &ptrptr
)); i
++)
654 int atype
= shishi_authorization_parse (val
);
657 shishi_warn (handle
, "Ignoring unknown authorization type: `%s'",
664 new = xrealloc (handle
->authorizationtypes
,
665 tot
* sizeof (*handle
->authorizationtypes
));
666 handle
->authorizationtypes
= new;
667 handle
->authorizationtypes
[tot
- 1] = atype
;
668 handle
->nauthorizationtypes
= tot
;