Add LIBTASN1_CFLAGS.
[shishi.git] / lib / principal.c
blob3ffa89dfa937c096197523cadb9514712e0fe50f
1 /* principal.c get and set default principal
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 /**
25 * shishi_principal_default_guess:
27 * Guesses a principal using getpwuid(getuid)), or if it fails, the
28 * string "user".
30 * Return value: Returns guessed default principal for user as a string that
31 * has to be deallocated with free() by the caller.
32 **/
33 char *
34 shishi_principal_default_guess (void)
36 uid_t uid;
37 struct passwd *pw;
39 uid = getuid ();
40 pw = getpwuid (uid);
42 if (pw)
43 return xstrdup (pw->pw_name);
44 else
45 return xstrdup ("user");
49 /**
50 * shishi_principal_default:
51 * @handle: Shishi library handle create by shishi_init().
53 * Return value: Returns the default principal name used in the
54 * library. (Not a copy of it, so don't modify or deallocate it.)
55 **/
56 const char *
57 shishi_principal_default (Shishi * handle)
59 if (!handle->default_principal)
61 char *p;
62 p = shishi_principal_default_guess ();
63 shishi_principal_default_set (handle, p);
64 free (p);
67 return handle->default_principal;
70 /**
71 * shishi_principal_default_set:
72 * @handle: Shishi library handle create by shishi_init().
73 * @principal: string with new default principal name, or NULL to
74 * reset to default.
76 * Set the default realm used in the library. The string is copied
77 * into the library, so you can dispose of the variable immediately
78 * after calling this function.
79 **/
80 void
81 shishi_principal_default_set (Shishi * handle, const char *principal)
83 if (handle->default_principal)
84 free (handle->default_principal);
85 if (principal)
86 handle->default_principal = xstrdup (principal);
87 else
88 handle->default_principal = NULL;
91 int
92 shishi_parse_name (Shishi * handle, const char *name,
93 char **principal, char **realm)
95 const char *p = name;
96 const char *q;
97 int escaped = 0;
99 if (!name)
100 return SHISHI_INVALID_PRINCIPAL_NAME;
102 while (*p && (*p != '@' || escaped))
103 if (escaped)
104 escaped = 0;
105 else if (*p++ == '\\')
106 escaped = 1;
108 if (principal)
110 *principal = xstrndup (name, p - name + 1);
111 (*principal)[p - name] = '\0';
114 if (*p)
116 q = ++p;
118 while (*q)
119 if (escaped)
120 escaped = 0;
121 else if (*q++ == '\\')
122 escaped = 1;
124 if (escaped)
125 return SHISHI_INVALID_PRINCIPAL_NAME;
127 if (realm)
128 *realm = xstrdup (p);
130 else if (realm)
131 *realm = xstrdup (shishi_realm_default (handle));
133 return SHISHI_OK;
137 2.1.1. Kerberos Principal Name Form
139 This name form shall be represented by the Object Identifier {iso(1)
140 member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
141 krb5(2) krb5_name(1)}. The recommended symbolic name for this type
142 is "GSS_KRB5_NT_PRINCIPAL_NAME".
144 This name type corresponds to the single-string representation of a
145 Kerberos name. (Within the MIT Kerberos V5 implementation, such
146 names are parseable with the krb5_parse_name() function.) The
147 elements included within this name representation are as follows,
148 proceeding from the beginning of the string:
150 (1) One or more principal name components; if more than one
151 principal name component is included, the components are
152 separated by `/`. Arbitrary octets may be included within
153 principal name components, with the following constraints and
154 special considerations:
156 (1a) Any occurrence of the characters `@` or `/` within a
157 name component must be immediately preceded by the `\`
158 quoting character, to prevent interpretation as a component
159 or realm separator.
161 (1b) The ASCII newline, tab, backspace, and null characters
162 may occur directly within the component or may be
163 represented, respectively, by `\n`, `\t`, `\b`, or `\0`.
165 (1c) If the `\` quoting character occurs outside the contexts
166 described in (1a) and (1b) above, the following character is
167 interpreted literally. As a special case, this allows the
168 doubled representation `\\` to represent a single occurrence
169 of the quoting character.
171 (1d) An occurrence of the `\` quoting character as the last
172 character of a component is illegal.
174 (2) Optionally, a `@` character, signifying that a realm name
175 immediately follows. If no realm name element is included, the
176 local realm name is assumed. The `/` , `:`, and null characters
177 may not occur within a realm name; the `@`, newline, tab, and
178 backspace characters may be included using the quoting
179 conventions described in (1a), (1b), and (1c) above.
183 shishi_principal_name_get (Shishi * handle,
184 Shishi_asn1 namenode,
185 const char *namefield, char *out, size_t * outlen)
187 int res;
188 char *format;
189 size_t totlen = 0;
190 int len;
191 int i, j, n;
193 /* FIXME: allocate output instead of writing inline */
195 asprintf (&format, "%s.name-string", namefield);
196 res = shishi_asn1_number_of_elements (handle, namenode, format, &n);
197 free (format);
198 if (res != SHISHI_OK)
199 return res;
201 totlen = 0;
202 for (i = 1; i <= n; i++)
204 len = *outlen - totlen;
205 asprintf (&format, "%s.name-string.?%d", namefield, i);
206 res = shishi_asn1_read (handle, namenode, format, &out[totlen], &len);
207 free (format);
208 if (res != SHISHI_OK)
209 return res;
211 for (j = 0; j < len; j++)
213 if (out[totlen] == '@' || out[totlen] == '/' || out[totlen] == '\\')
215 if (totlen + strlen ("\\") > *outlen)
216 return SHISHI_TOO_SMALL_BUFFER;
217 out[totlen + 1] = out[totlen];
218 out[totlen] = '\\';
219 len++;
220 totlen++;
221 j++;
223 totlen++;
226 if (i < n)
228 if (totlen + strlen ("/") > *outlen)
229 return SHISHI_TOO_SMALL_BUFFER;
230 out[totlen] = '/';
231 totlen++;
235 *outlen = totlen;
237 return SHISHI_OK;
241 shishi_principal_name_realm_get (Shishi * handle,
242 Shishi_asn1 namenode,
243 const char *namefield,
244 Shishi_asn1 realmnode,
245 const char *realmfield,
246 char *out, size_t * outlen)
248 int res;
249 size_t totlen = 0;
250 int len;
252 /* FIXME: allocate output instead of writing inline */
254 totlen = *outlen;
255 res = shishi_principal_name_get (handle, namenode, namefield, out, &totlen);
256 if (res != SHISHI_OK)
257 return res;
259 if (realmnode == NULL && realmfield)
261 if (totlen + strlen ("@") + strlen (realmfield) > *outlen)
262 return SHISHI_TOO_SMALL_BUFFER;
264 memcpy (out + totlen, "@", strlen ("@"));
265 totlen += strlen ("@");
266 memcpy (out + totlen, realmfield, strlen (realmfield));
267 totlen += strlen (realmfield);
269 else if (realmnode != NULL)
271 if (totlen + strlen ("@") > *outlen)
272 return SHISHI_TOO_SMALL_BUFFER;
274 memcpy (out + totlen, "@", strlen ("@"));
275 totlen += strlen ("@");
277 len = *outlen - totlen;
278 res = shishi_asn1_read (handle, realmnode, realmfield,
279 &out[totlen], &len);
280 if (res == SHISHI_ASN1_NO_ELEMENT)
281 totlen--;
282 else if (res != SHISHI_OK)
283 return res;
284 else
285 totlen += len;
288 *outlen = totlen;
290 return SHISHI_OK;
294 * shishi_principal_name_set:
295 * @handle: shishi handle as allocated by shishi_init().
296 * @namenode: ASN.1 structure with principal in @namefield.
297 * @namefield: name of field in namenode containing principal name.
298 * @name_type: type of principial, see Shishi_name_type, usually
299 * SHISHI_NT_UNKNOWN.
300 * @name: zero-terminated input array with principal name.
302 * Set the given principal name field to given name.
304 * Return value: Returns SHISHI_OK iff successful.
307 shishi_principal_name_set (Shishi * handle,
308 Shishi_asn1 namenode,
309 const char *namefield,
310 Shishi_name_type name_type, const char *name[])
312 int res;
313 char *asn1name;
314 int i;
316 asprintf (&asn1name, "%s.name-type", namefield);
317 res = shishi_asn1_write_int32 (handle, namenode, asn1name, name_type);
318 free (asn1name);
319 if (res != SHISHI_OK)
320 return res;
322 asprintf (&asn1name, "%s.name-string", namefield);
323 res = shishi_asn1_write (handle, namenode, asn1name, NULL, 0);
324 free (asn1name);
325 if (res != SHISHI_OK)
326 return res;
328 i = 1;
329 while (name[i - 1])
331 asprintf (&asn1name, "%s.name-string", namefield);
332 res = shishi_asn1_write (handle, namenode, asn1name, "NEW", 1);
333 free (asn1name);
334 if (res != SHISHI_OK)
335 return res;
337 asprintf (&asn1name, "%s.name-string.?%d", namefield, i);
338 res = shishi_asn1_write (handle, namenode, asn1name, name[i - 1], 0);
339 free (asn1name);
340 if (res != SHISHI_OK)
341 return res;
343 i++;
346 return SHISHI_OK;
350 * shishi_principal_set:
351 * @handle: shishi handle as allocated by shishi_init().
352 * @namenode: ASN.1 structure with principal in @namefield.
353 * @namefield: name of field in namenode containing principal name.
354 * @name: zero-terminated string with principal name on RFC 1964 form.
356 * Set principal name field in ASN.1 structure to given name.
358 * Return value: Returns SHISHI_OK iff successful.
361 shishi_principal_set (Shishi * handle,
362 Shishi_asn1 namenode,
363 const char *namefield, const char *name)
365 char *tmpname;
366 const char **namebuf;
367 char *tokptr;
368 int res;
369 int i;
371 tmpname = xstrdup (name);
372 namebuf = xmalloc (sizeof (*namebuf));
374 for (i = 0;
375 (namebuf[i] = strtok_r (i == 0 ? tmpname : NULL, "/", &tokptr)); i++)
377 namebuf = xrealloc (namebuf, (i + 2) * sizeof (*namebuf));
380 res = shishi_principal_name_set (handle, namenode, namefield,
381 SHISHI_NT_UNKNOWN, namebuf);
382 free (namebuf);
383 free (tmpname);
384 if (res != SHISHI_OK)
386 shishi_error_printf (handle, _("Could not set principal name: %s\n"),
387 shishi_strerror (res));
388 return res;
391 return SHISHI_OK;
394 char *
395 shishi_server_for_local_service (Shishi * handle, const char *service)
397 char buf[HOST_NAME_MAX];
398 int ret;
400 strcpy (buf, service);
401 strcat (buf, "/");
403 ret = gethostname (&buf[strlen (service) + 1],
404 sizeof (buf) - strlen (service) - 1);
405 buf[sizeof (buf) - 1] = '\0';
407 if (ret != 0)
408 strcpy (&buf[strlen (service) + 1], "localhost");
410 return xstrdup (buf);