Build gl/m4/Makefile.
[shishi.git] / lib / cfg.c
blob6d17bb86de75d2ec128a360cb846db66fb2861e6
1 /* cfg.c configuration file functions.
2 * Copyright (C) 2002, 2003 Simon Josefsson
4 * This file is part of Shishi.
6 * Shishi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * Shishi is distributed in the hope that it will be useful,
12 * but 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, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "internal.h"
24 enum
26 DEFAULT_REALM_OPTION = 0,
27 DEFAULT_PRINCIPAL_OPTION,
28 CLIENT_KDC_ETYPES_OPTION,
29 REALM_KDC_OPTION,
30 KDC_OPTION,
31 KDC_TIMEOUT_OPTION,
32 KDC_RETRIES_OPTION,
33 VERBOSE_CRYPTO_OPTION,
34 VERBOSE_ASN1_OPTION,
35 VERBOSE_NOICE_OPTION,
36 VERBOSE_OPTION,
37 STRINGPROCESS_OPTION,
38 THE_END
41 static char *const _shishi_opts[] = {
42 /* [DEFAULT_REALM_OPTION] = */ "default-realm",
43 /* [DEFAULT_PRINCIPAL_OPTION] = */ "default-principal",
44 /* [CLIENT_KDC_ETYPES_OPTION] = */ "client-kdc-etypes",
45 /* [REALM_KDC_OPTION] = */ "realm-kdc",
46 /* [KDC_OPTION] = */ "kdc",
47 /* [KDC_TIMEOUT_OPTION] = */ "kdc-timeout",
48 /* [KDC_RETRIES_OPTION] = */ "kdc-retries",
49 /* [VERBOSE_CRYPTO_OPTION] = */ "verbose-crypto",
50 /* [VERBOSE_ASN1_OPTION] = */ "verbose-asn1",
51 /* [VERBOSE_NOICE_OPTION] = */ "verbose-noice",
52 /* [VERBOSE_OPTION] = */ "verbose",
53 /* [STRINGPROCESS_OPTION] = */ "stringprocess",
54 /* [THE_END] = */ NULL
57 int getsubopt (char **optionp, char *const *tokens, char **valuep);
59 /**
60 * shishi_cfg:
61 * @option: string with shishi library option.
63 * Configure shishi library with given option.
65 * Return Value: Returns SHISHI_OK if option was valid.
66 **/
67 int
68 shishi_cfg (Shishi * handle, char *option)
70 char *value;
71 char *realm = NULL;
72 int res;
73 int i;
75 while (option != NULL && *option != '\0')
77 switch (getsubopt (&option, _shishi_opts, &value))
79 case KDC_TIMEOUT_OPTION:
80 if (value && atoi (value) > 0)
81 handle->kdctimeout = atoi (value);
82 else if (value)
83 shishi_warn (handle, "Invalid KDC timeout value: `%s'\n", value);
84 else
85 shishi_warn (handle, "Missing KDC timeout value.\n");
86 break;
88 case KDC_RETRIES_OPTION:
89 if (value && atoi (value) > 0)
90 handle->kdcretries = atoi (value);
91 else if (value)
92 shishi_warn (handle, "Invalid KDC retries value: `%s'\n", value);
93 else
94 shishi_warn (handle, "Missing KDC retries value.\n");
95 break;
97 case REALM_KDC_OPTION:
98 realm = strdup (value);
99 for (i = 0; i < handle->nrealminfos; i++)
100 if (strcmp (realm, handle->realminfos[i].name) == 0)
102 if (handle->realminfos[i].nkdcaddresses > 0 ||
103 handle->realminfos[i].kdcaddresses)
105 if (handle->realminfos[i].kdcaddresses)
106 free (handle->realminfos[i].kdcaddresses);
107 handle->realminfos[i].kdcaddresses = NULL;
108 handle->realminfos[i].nkdcaddresses = 0;
110 break;
112 handle->realminfos = realloc (handle->realminfos,
113 (handle->nrealminfos + 1) *
114 sizeof (*handle->realminfos));
115 if (handle->realminfos == NULL)
116 return SHISHI_MALLOC_ERROR;
117 handle->realminfos[handle->nrealminfos].name = realm;
118 handle->realminfos[handle->nrealminfos].kdcaddresses = NULL;
119 handle->realminfos[handle->nrealminfos].nkdcaddresses = 0;
120 handle->nrealminfos++;
121 break;
122 case DEFAULT_REALM_OPTION:
123 handle->default_realm = strdup (value);
124 break;
125 case DEFAULT_PRINCIPAL_OPTION:
126 handle->default_principal = strdup (value);
127 break;
128 case CLIENT_KDC_ETYPES_OPTION:
129 res = shishi_cfg_clientkdcetype_set (handle, value);
130 if (res != SHISHI_OK)
131 return res;
132 break;
133 case KDC_OPTION:
134 handle->kdc = strdup (value);
135 break;
136 case STRINGPROCESS_OPTION:
137 handle->stringprocess = strdup (value);
138 break;
139 case VERBOSE_OPTION:
140 handle->verbose = value && atoi (value) ? atoi (value) :
141 ~0 & ~VERBOSES;
142 break;
143 case VERBOSE_CRYPTO_OPTION:
144 handle->verbose |= SHISHI_VERBOSE_CRYPTO;
145 break;
146 case VERBOSE_ASN1_OPTION:
147 handle->verbose |= SHISHI_VERBOSE_ASN1;
148 break;
149 case VERBOSE_NOICE_OPTION:
150 handle->verbose |= SHISHI_VERBOSE_NOICE;
151 break;
152 case -1:
153 if (!value)
154 break;
155 for (i = 0; i < handle->nrealminfos; i++)
156 if (realm && handle->realminfos[i].name == realm)
158 struct Shishi_realminfo *ri = &handle->realminfos[i];
159 struct sockaddr_in *sinaddr;
160 struct hostent *he;
161 struct servent *se;
163 he = gethostbyname (value); /* XXX move to netio.c */
164 if (he == NULL ||
165 he->h_addr_list[0] == NULL || he->h_addrtype != AF_INET)
167 shishi_warn (handle,
168 "Unknown KDC host `%s' (h_errno %d)\n",
169 value, h_errno);
170 break;
173 ri->kdcaddresses = realloc (ri->kdcaddresses,
174 (ri->nkdcaddresses + 1) *
175 sizeof (*ri->kdcaddresses));
176 if (ri->kdcaddresses == NULL)
177 return SHISHI_MALLOC_ERROR;
178 ri->kdcaddresses[ri->nkdcaddresses].name = strdup (value);
179 sinaddr = (struct sockaddr_in *)
180 &ri->kdcaddresses[ri->nkdcaddresses].sockaddress;
181 memset (sinaddr, 0, sizeof (struct sockaddr));
182 ri->nkdcaddresses++;
184 sinaddr->sin_family = he->h_addrtype;
185 memcpy (&sinaddr->sin_addr, he->h_addr_list[0], he->h_length);
186 se = getservbyname ("kerberos", NULL);
187 if (se)
188 sinaddr->sin_port = se->s_port;
189 else
190 sinaddr->sin_port = htons (88);
192 if (realm)
193 break;
194 /* fall through */
196 default:
197 shishi_warn (handle, "Unknown option: `%s'\n", value);
198 break;
202 return SHISHI_OK;
206 * shishi_cfg_from_file:
207 * @cfg: filename to read configuration from.
209 * Configure shishi library using configuration file.
211 * Return Value: Returns SHISHI_OK iff succesful.
214 shishi_cfg_from_file (Shishi * handle, const char *cfg)
216 char line[BUFSIZ];
217 FILE *fh;
219 if (cfg == NULL)
220 return SHISHI_OK;
222 fh = fopen (cfg, "r");
223 if (fh == NULL)
225 shishi_warn (handle, "`%s': %s", cfg, strerror (errno));
226 return SHISHI_FOPEN_ERROR;
229 while (!feof (fh) && !ferror (fh))
231 if (!fgets (line, sizeof (line), fh))
232 continue;
234 line[strlen (line) - 1] = '\0';
236 while (line[0] && strchr (" \t\r\n", line[0]))
237 memmove (line, line + 1, strlen (line));
239 if (line[0] == '#' || line[0] == '\0')
240 continue;
242 if (strchr (line, ' ') && (strchr (line, '=') == NULL ||
243 strchr (line, ' ') < strchr (line, '=')))
245 char *p = strchr (line, ' ');
246 while (*(p + 1) == ' ' || *(p + 1) == '=')
247 memmove (p, p + 1, strlen (p + 1) + 1);
248 *p = '=';
251 shishi_cfg (handle, line);
254 if (fclose (fh) != 0)
255 return SHISHI_FCLOSE_ERROR;
257 if (VERBOSE (handle))
258 shishi_cfg_print (handle, stdout);
260 return SHISHI_OK;
264 * shishi_cfg_print:
265 * @handle: Shishi library handle create by shishi_init().
266 * @fh: file descriptor opened for writing.
268 * Print library configuration status, mostly for debugging purposes.
270 * Return Value: Returns SHISHI_OK.
273 shishi_cfg_print (Shishi * handle, FILE * fh)
275 int i, j;
277 fprintf (fh, "Shishi initial library configuration:\n");
278 fprintf (fh, "\tDefault realm: %s\n",
279 handle->default_realm ? handle->default_realm : "(NULL)");
280 fprintf (fh, "\tDefault principal: %s\n",
281 handle->default_principal ? handle->default_principal : "(NULL)");
282 fprintf (fh, "\tClient KDC etypes:");
283 for (i = 0; i < handle->nclientkdcetypes; i++)
284 fprintf (fh, " %s", shishi_cipher_name (handle->clientkdcetypes[i]));
285 fprintf (fh, "\n");
286 fprintf (fh, "\tKDC: %s\n", handle->kdc ? handle->kdc : "(NULL)");
287 fprintf (fh, "\tVerbose: %d\n", handle->verbose);
288 for (i = 0; i < handle->nrealminfos; i++)
290 fprintf (fh, "\tRealm %s's KDCs:", handle->realminfos[i].name);
291 for (j = 0; j < handle->realminfos[i].nkdcaddresses; j++)
292 fprintf (fh, " %s (%s)", handle->realminfos[i].kdcaddresses[j].name,
293 inet_ntoa (((struct sockaddr_in *) &handle->realminfos[i].
294 kdcaddresses[j].sockaddress)->sin_addr));
295 fprintf (fh, "\n");
298 return SHISHI_OK;
302 * shishi_cfg_default_systemfile:
303 * @handle: Shishi library handle create by shishi_init().
305 * Return value: Return system configuration filename.
307 const char *
308 shishi_cfg_default_systemfile (Shishi * handle)
310 return SYSTEMCFGFILE;
314 * shishi_cfg_default_userfile:
315 * @handle: Shishi library handle create by shishi_init().
317 * Return value: Return user configuration filename.
319 const char *
320 shishi_cfg_default_userfile (Shishi * handle)
322 char *home;
324 if (!handle->usercfgfile)
326 home = getenv ("HOME");
328 if (home == NULL)
329 home = "";
331 asprintf (&handle->usercfgfile, "%s%s", home, USERCFG_FILE);
334 return handle->usercfgfile;
338 * shishi_cfg_clientkdcetype:
339 * @handle: Shishi library handle create by shishi_init().
340 * @etypes: output array with encryption types.
342 * Set the etypes variable to the array of preferred client etypes.
344 * Return value: Return the number of encryption types in the array,
345 * 0 means none.
348 shishi_cfg_clientkdcetype (Shishi * handle, int **etypes)
350 *etypes = handle->clientkdcetypes;
351 return handle->nclientkdcetypes;
355 * shishi_cfg_clientkdcetype_set:
356 * @handle: Shishi library handle create by shishi_init().
357 * @value: string with encryption types.
359 * Set the "client-kdc-etypes" configuration option from given string.
360 * The string contains encryption types (integer or names) separated
361 * by comma or whitespace, e.g. "aes256-cts-hmac-sha1-96
362 * des3-cbc-sha1-kd des-cbc-md5".
364 * Return value: Return SHISHI_OK iff successful.
367 shishi_cfg_clientkdcetype_set (Shishi * handle, char *value)
369 char *ptrptr;
370 char *val;
371 int i;
372 int tot = 0;
374 if (value == NULL || *value == '\0')
375 return SHISHI_OK;
377 for (i = 0; (val = strtok_r (i == 0 ? value : NULL, ", \t", &ptrptr)); i++)
379 int etype = shishi_cipher_parse (val);
381 if (etype == -1)
382 shishi_warn (handle, "Ignoring unknown encryption type: `%s'\n", val);
383 else
385 int *new;
387 tot++;
388 new = realloc (handle->clientkdcetypes,
389 tot * sizeof (*handle->clientkdcetypes));
390 if (handle->clientkdcetypes == NULL)
391 return SHISHI_MALLOC_ERROR;
392 handle->clientkdcetypes = new;
393 handle->clientkdcetypes[tot - 1] = etype;
394 handle->nclientkdcetypes = tot;
398 return SHISHI_OK;