1 /* principal.c --- Get and set default principal.
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
26 * shishi_principal_default_guess:
28 * Guesses the principal name for the user, looking at environment
29 * variables SHISHI_USER and USER, or if that fails, returns the
32 * Return value: Returns guessed default principal for user as a
33 * string that has to be deallocated with free() by the caller.
36 shishi_principal_default_guess (void)
40 envuser
= getenv ("SHISHI_USER");
42 envuser
= getenv ("USER");
46 return xstrdup (envuser
);
51 * shishi_principal_default:
52 * @handle: Shishi library handle create by shishi_init().
54 * The default principal name is the name in the environment variable
55 * USER, but can be overridden by specifying the environment variable
58 * Return value: Returns the default principal name used in the
59 * library. (Not a copy of it, so don't modify or deallocate it.)
62 shishi_principal_default (Shishi
* handle
)
64 if (!handle
->default_principal
)
67 p
= shishi_principal_default_guess ();
68 shishi_principal_default_set (handle
, p
);
72 return handle
->default_principal
;
76 * shishi_principal_default_set:
77 * @handle: Shishi library handle create by shishi_init().
78 * @principal: string with new default principal name, or NULL to
81 * Set the default realm used in the library. The string is copied
82 * into the library, so you can dispose of the variable immediately
83 * after calling this function.
86 shishi_principal_default_set (Shishi
* handle
, const char *principal
)
88 if (handle
->default_principal
)
89 free (handle
->default_principal
);
91 handle
->default_principal
= xstrdup (principal
);
93 handle
->default_principal
= NULL
;
98 * @handle: Shishi library handle create by shishi_init().
99 * @name: Input principal name string, e.g. imap/mail.gnu.org@GNU.ORG.
100 * @principal: newly allocated output string with principal name.
101 * @realm: newly allocated output string with realm name.
103 * Split up principal name (e.g., "simon@JOSEFSSON.ORG") into two
104 * newly allocated strings, the principal ("simon") and realm
105 * ("JOSEFSSON.ORG"). If there is no realm part in NAME, REALM is set
108 * Return value: Returns SHISHI_INVALID_PRINCIPAL_NAME if NAME is NULL
109 * or ends with the escape character "\", or SHISHI_OK iff
113 shishi_parse_name (Shishi
* handle
, const char *name
,
114 char **principal
, char **realm
)
116 const char *p
= name
;
121 return SHISHI_INVALID_PRINCIPAL_NAME
;
123 while (*p
&& (*p
!= '@' || escaped
))
126 else if (*p
++ == '\\')
130 return SHISHI_INVALID_PRINCIPAL_NAME
;
134 *principal
= xstrndup (name
, p
- name
+ 1);
135 (*principal
)[p
- name
] = '\0';
145 else if (*q
++ == '\\')
149 return SHISHI_INVALID_PRINCIPAL_NAME
;
152 *realm
= xstrdup (p
);
161 * shishi_principal_name:
162 * @handle: Shishi library handle create by shishi_init().
163 * @namenode: ASN.1 structure with principal in @namefield.
164 * @namefield: name of field in @namenode containing principal name.
165 * @out: pointer to newly allocated zero terminated string containing
166 * principal name. May be %NULL (to only populate @outlen).
167 * @outlen: pointer to length of @out on output, excluding terminating
168 * zero. May be %NULL (to only populate @out).
170 * Represent principal name in ASN.1 structure as zero-terminated
171 * string. The string is allocate by this function, and it is the
172 * responsibility of the caller to deallocate it. Note that the
173 * output length @outlen does not include the terminating zero.
175 * Return value: Returns SHISHI_OK iff successful.
178 shishi_principal_name (Shishi
* handle
,
179 Shishi_asn1 namenode
,
180 const char *namefield
, char **out
, size_t * outlen
)
188 asprintf (&format
, "%s.name-string", namefield
);
189 res
= shishi_asn1_number_of_elements (handle
, namenode
, format
, &n
);
191 if (res
!= SHISHI_OK
)
194 for (i
= 1; i
<= n
; i
++)
200 asprintf (&format
, "%s.name-string.?%d", namefield
, i
);
201 res
= shishi_asn1_read (handle
, namenode
, format
, &tmp
, &tmplen
);
203 if (res
!= SHISHI_OK
)
207 for (j
= 0; j
< tmplen
; j
++)
208 if (tmp
[j
] == '@' || tmp
[j
] == '/' || tmp
[j
] == '\\')
213 name
= xrealloc (name
, namelen
+ safetmplen
);
215 for (j
= 0; j
< tmplen
; j
++)
217 if (tmp
[j
] == '@' || tmp
[j
] == '/' || tmp
[j
] == '\\')
218 name
[namelen
++] = '\\';
219 name
[namelen
++] = tmp
[j
];
223 name
[namelen
++] = '/';
228 name
= xrealloc (name
, namelen
+ 1);
229 name
[namelen
] = '\0';
242 * shishi_principal_name_realm:
243 * @handle: Shishi library handle create by shishi_init().
244 * @namenode: ASN.1 structure with principal name in @namefield.
245 * @namefield: name of field in @namenode containing principal name.
246 * @realmnode: ASN.1 structure with principal realm in @realmfield.
247 * @realmfield: name of field in @realmnode containing principal realm.
248 * @out: pointer to newly allocated zero terminated string containing
249 * principal name. May be %NULL (to only populate @outlen).
250 * @outlen: pointer to length of @out on output, excluding terminating
251 * zero. May be %NULL (to only populate @out).
253 * Represent principal name and realm in ASN.1 structure as
254 * zero-terminated string. The string is allocate by this function,
255 * and it is the responsibility of the caller to deallocate it. Note
256 * that the output length @outlen does not include the terminating
259 * Return value: Returns SHISHI_OK iff successful.
262 shishi_principal_name_realm (Shishi
* handle
,
263 Shishi_asn1 namenode
,
264 const char *namefield
,
265 Shishi_asn1 realmnode
,
266 const char *realmfield
,
267 char **out
, size_t * outlen
)
273 rc
= shishi_principal_name (handle
, namenode
, namefield
, &tmp
, &tmplen
);
277 if (realmnode
== NULL
&& realmfield
)
279 size_t realmfieldlen
= strlen (realmfield
);
281 tmp
= xrealloc (tmp
, tmplen
+ 1 + realmfieldlen
+ 1);
284 memcpy (tmp
+ tmplen
+ 1, realmfield
, realmfieldlen
);
286 tmplen
+= 1 + realmfieldlen
;
290 else if (realmnode
!= NULL
)
295 rc
= shishi_asn1_read (handle
, realmnode
, realmfield
,
303 tmp
= xrealloc (tmp
, tmplen
+ 1 + realmlen
+ 1);
306 memcpy (tmp
+ tmplen
+ 1, realm
, realmlen
);
308 tmplen
+= 1 + realmlen
;
323 * shishi_principal_name_set:
324 * @handle: shishi handle as allocated by shishi_init().
325 * @namenode: ASN.1 structure with principal in @namefield.
326 * @namefield: name of field in namenode containing principal name.
327 * @name_type: type of principial, see Shishi_name_type, usually
329 * @name: zero-terminated input array with principal name.
331 * Set the given principal name field to given name.
333 * Return value: Returns SHISHI_OK iff successful.
336 shishi_principal_name_set (Shishi
* handle
,
337 Shishi_asn1 namenode
,
338 const char *namefield
,
339 Shishi_name_type name_type
, const char *name
[])
345 asprintf (&asn1name
, "%s.name-type", namefield
);
346 res
= shishi_asn1_write_int32 (handle
, namenode
, asn1name
, name_type
);
348 if (res
!= SHISHI_OK
)
351 asprintf (&asn1name
, "%s.name-string", namefield
);
352 res
= shishi_asn1_write (handle
, namenode
, asn1name
, NULL
, 0);
354 if (res
!= SHISHI_OK
)
360 asprintf (&asn1name
, "%s.name-string", namefield
);
361 res
= shishi_asn1_write (handle
, namenode
, asn1name
, "NEW", 1);
363 if (res
!= SHISHI_OK
)
366 asprintf (&asn1name
, "%s.name-string.?%d", namefield
, i
);
367 res
= shishi_asn1_write (handle
, namenode
, asn1name
, name
[i
- 1], 0);
369 if (res
!= SHISHI_OK
)
379 * shishi_principal_set:
380 * @handle: shishi handle as allocated by shishi_init().
381 * @namenode: ASN.1 structure with principal in @namefield.
382 * @namefield: name of field in namenode containing principal name.
383 * @name: zero-terminated string with principal name on RFC 1964 form.
385 * Set principal name field in ASN.1 structure to given name.
387 * Return value: Returns SHISHI_OK iff successful.
390 shishi_principal_set (Shishi
* handle
,
391 Shishi_asn1 namenode
,
392 const char *namefield
, const char *name
)
395 const char **namebuf
;
400 tmpname
= xstrdup (name
);
401 namebuf
= xmalloc (sizeof (*namebuf
));
404 (namebuf
[i
] = strtok_r (i
== 0 ? tmpname
: NULL
, "/", &tokptr
)); i
++)
406 namebuf
= xrealloc (namebuf
, (i
+ 2) * sizeof (*namebuf
));
409 res
= shishi_principal_name_set (handle
, namenode
, namefield
,
410 SHISHI_NT_UNKNOWN
, namebuf
);
413 if (res
!= SHISHI_OK
)
415 shishi_error_printf (handle
, _("Could not set principal name: %s\n"),
416 shishi_strerror (res
));
424 * shishi_derive_default_salt:
425 * @handle: shishi handle as allocated by shishi_init().
426 * @name: principal name of user.
427 * @salt: output variable with newly allocated salt string.
429 * Derive the default salt from a principal. The default salt is the
430 * concatenation of the decoded realm and principal.
432 * Return value: Return SHISHI_OK if successful.
435 shishi_derive_default_salt (Shishi
* handle
,
443 rc
= shishi_parse_name (handle
, name
, &principal
, &realm
);
447 if (!principal
|| !realm
)
453 return SHISHI_INVALID_PRINCIPAL_NAME
;
456 *salt
= xasprintf ("%s%s", realm
, principal
);
465 * shishi_server_for_local_service:
466 * @handle: shishi handle as allocated by shishi_init().
467 * @service: zero terminated string with name of service, e.g., "host".
469 * Construct a service principal (e.g., "imap/yxa.extuno.com") based
470 * on supplied service name (i.e., "imap") and the system hostname as
471 * returned by hostname() (i.e., "yxa.extundo.com"). The string must
472 * be deallocated by the caller.
474 * Return value: Return newly allocated service name string.
477 shishi_server_for_local_service (Shishi
* handle
, const char *service
)
482 hostname
= xgethostname ();
484 asprintf (&server
, "%s/%s", service
, hostname
);