1
/* keyutils.c: key utility library
3
* Copyright (C) 2005,2011 Red Hat, Inc. All Rights Reserved.
4
* Written by David Howells (dhowells@redhat.com)
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Lesser General Public License
8
* as published by the Free Software Foundation; either version
9
* 2 of the License, or (at your option) any later version.
21
#include <asm/unistd.h>
24
const char keyutils_version_string[] = PKGVERSION;
25
const char keyutils_build_string[] = PKGBUILD;
27
#ifdef NO_GLIBC_KEYERR
28
static int error_inited;
29
static void (*libc_perror)(const char *msg);
30
static char *(*libc_strerror_r)(int errnum, char *buf, size_t n);
31
//static int (*libc_xpg_strerror_r)(int errnum, char *buf, size_t n);
32
#define RTLD_NEXT ((void *) -1L)
35
#define __weak __attribute__((weak))
37
key_serial_t __weak add_key(const char *type,
38
const char *description,
43
return syscall(__NR_add_key,
44
type, description, payload, plen, ringid);
47
key_serial_t __weak request_key(const char *type,
48
const char *description,
49
const char * callout_info,
50
key_serial_t destringid)
52
return syscall(__NR_request_key,
53
type, description, callout_info, destringid);
56
static inline long __keyctl(int cmd,
62
return syscall(__NR_keyctl,
63
cmd, arg2, arg3, arg4, arg5);
66
long __weak keyctl(int cmd, ...)
69
unsigned long arg2, arg3, arg4, arg5;
72
arg2 = va_arg(va, unsigned long);
73
arg3 = va_arg(va, unsigned long);
74
arg4 = va_arg(va, unsigned long);
75
arg5 = va_arg(va, unsigned long);
78
return __keyctl(cmd, arg2, arg3, arg4, arg5);
81
key_serial_t keyctl_get_keyring_ID(key_serial_t id, int create)
83
return keyctl(KEYCTL_GET_KEYRING_ID, id, create);
86
key_serial_t keyctl_join_session_keyring(const char *name)
88
return keyctl(KEYCTL_JOIN_SESSION_KEYRING, name);
91
long keyctl_update(key_serial_t id, const void *payload, size_t plen)
93
return keyctl(KEYCTL_UPDATE, id, payload, plen);
96
long keyctl_revoke(key_serial_t id)
98
return keyctl(KEYCTL_REVOKE, id);
101
long keyctl_chown(key_serial_t id, uid_t uid, gid_t gid)
103
return keyctl(KEYCTL_CHOWN, id, uid, gid);
106
long keyctl_setperm(key_serial_t id, key_perm_t perm)
108
return keyctl(KEYCTL_SETPERM, id, perm);
111
long keyctl_describe(key_serial_t id, char *buffer, size_t buflen)
113
return keyctl(KEYCTL_DESCRIBE, id, buffer, buflen);
116
long keyctl_clear(key_serial_t ringid)
118
return keyctl(KEYCTL_CLEAR, ringid);
121
long keyctl_link(key_serial_t id, key_serial_t ringid)
123
return keyctl(KEYCTL_LINK, id, ringid);
126
long keyctl_unlink(key_serial_t id, key_serial_t ringid)
128
return keyctl(KEYCTL_UNLINK, id, ringid);
131
long keyctl_search(key_serial_t ringid,
133
const char *description,
134
key_serial_t destringid)
136
return keyctl(KEYCTL_SEARCH, ringid, type, description, destringid);
139
long keyctl_read(key_serial_t id, char *buffer, size_t buflen)
141
return keyctl(KEYCTL_READ, id, buffer, buflen);
144
long keyctl_instantiate(key_serial_t id,
149
return keyctl(KEYCTL_INSTANTIATE, id, payload, plen, ringid);
152
long keyctl_negate(key_serial_t id, unsigned timeout, key_serial_t ringid)
154
return keyctl(KEYCTL_NEGATE, id, timeout, ringid);
157
long keyctl_set_reqkey_keyring(int reqkey_defl)
159
return keyctl(KEYCTL_SET_REQKEY_KEYRING, reqkey_defl);
162
long keyctl_set_timeout(key_serial_t id, unsigned timeout)
164
return keyctl(KEYCTL_SET_TIMEOUT, id, timeout);
167
long keyctl_assume_authority(key_serial_t id)
169
return keyctl(KEYCTL_ASSUME_AUTHORITY, id);
172
long keyctl_get_security(key_serial_t id, char *buffer, size_t buflen)
174
return keyctl(KEYCTL_GET_SECURITY, id, buffer, buflen);
177
long keyctl_session_to_parent(void)
179
return keyctl(KEYCTL_SESSION_TO_PARENT);
182
long keyctl_reject(key_serial_t id, unsigned timeout, unsigned error,
185
long ret = keyctl(KEYCTL_REJECT, id, timeout, error, ringid);
187
/* fall back to keyctl_negate() if this op is not supported by this
189
if (ret == -1 && errno == EOPNOTSUPP)
190
return keyctl_negate(id, timeout, ringid);
194
long keyctl_instantiate_iov(key_serial_t id,
195
const struct iovec *payload_iov,
199
long ret = keyctl(KEYCTL_INSTANTIATE_IOV, id, payload_iov, ioc, ringid);
201
/* fall back to keyctl_instantiate() if this op is not supported by
202
* this kernel version */
203
if (ret == -1 && errno == EOPNOTSUPP) {
205
size_t bsize = 0, seg;
208
if (!payload_iov || !ioc)
209
return keyctl_instantiate(id, NULL, 0, ringid);
210
for (loop = 0; loop < ioc; loop++)
211
bsize += payload_iov[loop].iov_len;
213
return keyctl_instantiate(id, NULL, 0, ringid);
214
p = buf = malloc(bsize);
217
for (loop = 0; loop < ioc; loop++) {
218
seg = payload_iov[loop].iov_len;
219
p = memcpy(p, payload_iov[loop].iov_base, seg) + seg;
221
ret = keyctl_instantiate(id, buf, bsize, ringid);
227
/*****************************************************************************/
229
* fetch key description into an allocated buffer
230
* - resulting string is NUL terminated
231
* - returns count not including NUL
233
int keyctl_describe_alloc(key_serial_t id, char **_buffer)
238
ret = keyctl_describe(id, NULL, 0);
243
buf = malloc(buflen);
248
ret = keyctl_describe(id, buf, buflen);
256
buf = realloc(buf, buflen);
264
} /* end keyctl_describe_alloc() */
266
/*****************************************************************************/
268
* fetch key contents into an allocated buffer
269
* - resulting buffer has an extra NUL added to the end
270
* - returns count (not including extraneous NUL)
272
int keyctl_read_alloc(key_serial_t id, void **_buffer)
277
ret = keyctl_read(id, NULL, 0);
282
buf = malloc(buflen + 1);
287
ret = keyctl_read(id, buf, buflen);
295
buf = realloc(buf, buflen + 1);
300
((unsigned char *) buf)[buflen] = 0;
304
} /* end keyctl_read_alloc() */
306
/*****************************************************************************/
308
* fetch key security label into an allocated buffer
309
* - resulting string is NUL terminated
310
* - returns count not including NUL
312
int keyctl_get_security_alloc(key_serial_t id, char **_buffer)
317
ret = keyctl_get_security(id, NULL, 0);
322
buf = malloc(buflen);
327
ret = keyctl_get_security(id, buf, buflen);
335
buf = realloc(buf, buflen);
345
* Depth-first recursively apply a function over a keyring tree
347
static int recursive_key_scan_aux(key_serial_t parent, key_serial_t key,
348
int depth, recursive_key_scanner_t func,
355
char *desc, type[255];
356
int desc_len, uid, gid, ret, n, kcount = 0;
361
/* read the key description */
363
desc_len = keyctl_describe_alloc(key, &desc);
370
n = sscanf(desc, "%[^;];%d;%d;%x;", type, &uid, &gid, &perm);
379
/* if it's a keyring then we're going to want to recursively search it
381
if (strcmp(type, "keyring") == 0) {
382
/* read the keyring's contents */
383
ret = keyctl_read_alloc(key, &ring);
389
/* walk the keyring */
392
ringlen >= sizeof(key_serial_t);
393
ringlen -= sizeof(key_serial_t)
395
kcount += recursive_key_scan_aux(key, *pk++, depth + 1,
402
kcount += func(parent, key, desc, desc_len, data);
408
* Depth-first apply a function over a keyring tree
410
int recursive_key_scan(key_serial_t key, recursive_key_scanner_t func, void *data)
412
return recursive_key_scan_aux(0, key, 0, func, data);
416
* Depth-first apply a function over session keyring tree
418
int recursive_session_key_scan(recursive_key_scanner_t func, void *data)
420
key_serial_t session =
421
keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 0);
423
return recursive_key_scan(session, func, data);
427
#ifdef NO_GLIBC_KEYERR
428
/*****************************************************************************/
430
* initialise error handling
432
static void error_init(void)
440
libc_perror = dlsym(RTLD_NEXT,"perror");
442
fprintf(stderr, "Failed to look up next perror\n");
445
fprintf(stderr, "%s\n", err);
449
//fprintf(stderr, "next perror at %p\n", libc_perror);
451
libc_strerror_r = dlsym(RTLD_NEXT,"strerror_r");
452
if (!libc_strerror_r) {
453
fprintf(stderr, "Failed to look up next strerror_r\n");
456
fprintf(stderr, "%s\n", err);
460
//fprintf(stderr, "next strerror_r at %p\n", libc_strerror_r);
463
libc_xpg_strerror_r = dlsym(RTLD_NEXT,"xpg_strerror_r");
464
if (!libc_xpg_strerror_r) {
465
fprintf(stderr, "Failed to look up next xpg_strerror_r\n");
468
fprintf(stderr, "%s\n", err);
472
//fprintf(stderr, "next xpg_strerror_r at %p\n", libc_xpg_strerror_r);
475
} /* end error_init() */
477
/*****************************************************************************/
479
* overload glibc's strerror_r() with a version that knows about key errors
481
char *strerror_r(int errnum, char *buf, size_t n)
493
errstr = "Requested key not available";
497
errstr = "Key has expired";
501
errstr = "Key has been revoked";
505
errstr = "Key was rejected by service";
509
return libc_strerror_r(errnum, buf, n);
512
len = strlen(errstr) + 1;
516
memcpy(buf, errstr, n - 1);
522
memcpy(buf, errstr, len);
526
} /* end strerror_r() */
529
/*****************************************************************************/
531
* overload glibc's strerror_r() with a version that knows about key errors
533
int xpg_strerror_r(int errnum, char *buf, size_t n)
543
errstr = "Requested key not available";
547
errstr = "Key has expired";
551
errstr = "Key has been revoked";
555
errstr = "Key was rejected by service";
559
return libc_xpg_strerror_r(errnum, buf, n);
562
len = strlen(errstr) + 1;
566
memcpy(buf, errstr, n - 1);
572
memcpy(buf, errstr, len);
576
} /* end xpg_strerror_r() */
579
/*****************************************************************************/
583
void perror(const char *msg)
590
fprintf(stderr, "%s: Requested key not available\n", msg);
594
fprintf(stderr, "%s: Key has expired\n", msg);
598
fprintf(stderr, "%s: Key has been revoked\n", msg);
602
fprintf(stderr, "%s: Key was rejected by service\n", msg);