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);
228
/*****************************************************************************/
230
* plain realloc is just crazy
232
static void* __xrealloc(void* ptr, size_t size)
236
ret = realloc(ptr, size);
245
/*****************************************************************************/
247
* fetch key description into an allocated buffer
248
* - resulting string is NUL terminated
249
* - returns count not including NUL
251
int keyctl_describe_alloc(key_serial_t id, char **_buffer)
256
ret = keyctl_describe(id, NULL, 0);
261
buf = malloc(buflen);
266
ret = keyctl_describe(id, buf, buflen);
274
buf = __xrealloc(buf, buflen);
282
} /* end keyctl_describe_alloc() */
284
/*****************************************************************************/
286
* fetch key contents into an allocated buffer
287
* - resulting buffer has an extra NUL added to the end
288
* - returns count (not including extraneous NUL)
290
int keyctl_read_alloc(key_serial_t id, void **_buffer)
295
ret = keyctl_read(id, NULL, 0);
300
buf = malloc(buflen + 1);
305
ret = keyctl_read(id, buf, buflen);
313
buf = __xrealloc(buf, buflen + 1);
318
((unsigned char *) buf)[buflen] = 0;
322
} /* end keyctl_read_alloc() */
324
/*****************************************************************************/
326
* fetch key security label into an allocated buffer
327
* - resulting string is NUL terminated
328
* - returns count not including NUL
330
int keyctl_get_security_alloc(key_serial_t id, char **_buffer)
335
ret = keyctl_get_security(id, NULL, 0);
340
buf = malloc(buflen);
345
ret = keyctl_get_security(id, buf, buflen);
353
buf = realloc(buf, buflen);
363
* Depth-first recursively apply a function over a keyring tree
365
static int recursive_key_scan_aux(key_serial_t parent, key_serial_t key,
366
int depth, recursive_key_scanner_t func,
373
char *desc, type[255];
374
int desc_len, uid, gid, ret, n, kcount = 0;
379
/* read the key description */
381
desc_len = keyctl_describe_alloc(key, &desc);
388
n = sscanf(desc, "%[^;];%d;%d;%x;", type, &uid, &gid, &perm);
397
/* if it's a keyring then we're going to want to recursively search it
399
if (strcmp(type, "keyring") == 0) {
400
/* read the keyring's contents */
401
ret = keyctl_read_alloc(key, &ring);
407
/* walk the keyring */
410
ringlen >= sizeof(key_serial_t);
411
ringlen -= sizeof(key_serial_t)
413
kcount += recursive_key_scan_aux(key, *pk++, depth + 1,
420
kcount += func(parent, key, desc, desc_len, data);
426
* Depth-first apply a function over a keyring tree
428
int recursive_key_scan(key_serial_t key, recursive_key_scanner_t func, void *data)
430
return recursive_key_scan_aux(0, key, 0, func, data);
434
* Depth-first apply a function over session keyring tree
436
int recursive_session_key_scan(recursive_key_scanner_t func, void *data)
438
key_serial_t session =
439
keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 0);
441
return recursive_key_scan(session, func, data);
445
#ifdef NO_GLIBC_KEYERR
446
/*****************************************************************************/
448
* initialise error handling
450
static void error_init(void)
458
libc_perror = dlsym(RTLD_NEXT,"perror");
460
fprintf(stderr, "Failed to look up next perror\n");
463
fprintf(stderr, "%s\n", err);
467
//fprintf(stderr, "next perror at %p\n", libc_perror);
469
libc_strerror_r = dlsym(RTLD_NEXT,"strerror_r");
470
if (!libc_strerror_r) {
471
fprintf(stderr, "Failed to look up next strerror_r\n");
474
fprintf(stderr, "%s\n", err);
478
//fprintf(stderr, "next strerror_r at %p\n", libc_strerror_r);
481
libc_xpg_strerror_r = dlsym(RTLD_NEXT,"xpg_strerror_r");
482
if (!libc_xpg_strerror_r) {
483
fprintf(stderr, "Failed to look up next xpg_strerror_r\n");
486
fprintf(stderr, "%s\n", err);
490
//fprintf(stderr, "next xpg_strerror_r at %p\n", libc_xpg_strerror_r);
493
} /* end error_init() */
495
/*****************************************************************************/
497
* overload glibc's strerror_r() with a version that knows about key errors
499
char *strerror_r(int errnum, char *buf, size_t n)
511
errstr = "Requested key not available";
515
errstr = "Key has expired";
519
errstr = "Key has been revoked";
523
errstr = "Key was rejected by service";
527
return libc_strerror_r(errnum, buf, n);
530
len = strlen(errstr) + 1;
534
memcpy(buf, errstr, n - 1);
540
memcpy(buf, errstr, len);
544
} /* end strerror_r() */
547
/*****************************************************************************/
549
* overload glibc's strerror_r() with a version that knows about key errors
551
int xpg_strerror_r(int errnum, char *buf, size_t n)
561
errstr = "Requested key not available";
565
errstr = "Key has expired";
569
errstr = "Key has been revoked";
573
errstr = "Key was rejected by service";
577
return libc_xpg_strerror_r(errnum, buf, n);
580
len = strlen(errstr) + 1;
584
memcpy(buf, errstr, n - 1);
590
memcpy(buf, errstr, len);
594
} /* end xpg_strerror_r() */
597
/*****************************************************************************/
601
void perror(const char *msg)
608
fprintf(stderr, "%s: Requested key not available\n", msg);
612
fprintf(stderr, "%s: Key has expired\n", msg);
616
fprintf(stderr, "%s: Key has been revoked\n", msg);
620
fprintf(stderr, "%s: Key was rejected by service\n", msg);