~ubuntu-branches/ubuntu/saucy/keyutils/saucy

« back to all changes in this revision

Viewing changes to .pc/0002-another-memleak.patch/keyutils.c

  • Committer: Package Import Robot
  • Author(s): Luk Claes
  • Date: 2013-04-06 09:38:50 UTC
  • mfrom: (10.2.11 sid)
  • Revision ID: package-import@ubuntu.com-20130406093850-e6xnevgf3za1t4y3
Tags: 1.5.5-7
* Taking over with maintainer's consent.
* Adding watch file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* keyutils.c: key utility library
 
2
 *
 
3
 * Copyright (C) 2005,2011 Red Hat, Inc. All Rights Reserved.
 
4
 * Written by David Howells (dhowells@redhat.com)
 
5
 *
 
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.
 
10
 */
 
11
 
 
12
#include <stdio.h>
 
13
#include <stdlib.h>
 
14
#include <stdint.h>
 
15
#include <stdarg.h>
 
16
#include <string.h>
 
17
#include <unistd.h>
 
18
#include <dlfcn.h>
 
19
#include <sys/uio.h>
 
20
#include <errno.h>
 
21
#include <asm/unistd.h>
 
22
#include "keyutils.h"
 
23
 
 
24
const char keyutils_version_string[] = PKGVERSION;
 
25
const char keyutils_build_string[] = PKGBUILD;
 
26
 
 
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)
 
33
#endif
 
34
 
 
35
#define __weak __attribute__((weak))
 
36
 
 
37
key_serial_t __weak add_key(const char *type,
 
38
                            const char *description,
 
39
                            const void *payload,
 
40
                            size_t plen,
 
41
                            key_serial_t ringid)
 
42
{
 
43
        return syscall(__NR_add_key,
 
44
                       type, description, payload, plen, ringid);
 
45
}
 
46
 
 
47
key_serial_t __weak request_key(const char *type,
 
48
                                const char *description,
 
49
                                const char * callout_info,
 
50
                                key_serial_t destringid)
 
51
{
 
52
        return syscall(__NR_request_key,
 
53
                       type, description, callout_info, destringid);
 
54
}
 
55
 
 
56
static inline long __keyctl(int cmd,
 
57
                            unsigned long arg2,
 
58
                            unsigned long arg3,
 
59
                            unsigned long arg4,
 
60
                            unsigned long arg5)
 
61
{
 
62
        return syscall(__NR_keyctl,
 
63
                       cmd, arg2, arg3, arg4, arg5);
 
64
}
 
65
 
 
66
long __weak keyctl(int cmd, ...)
 
67
{
 
68
        va_list va;
 
69
        unsigned long arg2, arg3, arg4, arg5;
 
70
 
 
71
        va_start(va, cmd);
 
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);
 
76
        va_end(va);
 
77
 
 
78
        return __keyctl(cmd, arg2, arg3, arg4, arg5);
 
79
}
 
80
 
 
81
key_serial_t keyctl_get_keyring_ID(key_serial_t id, int create)
 
82
{
 
83
        return keyctl(KEYCTL_GET_KEYRING_ID, id, create);
 
84
}
 
85
 
 
86
key_serial_t keyctl_join_session_keyring(const char *name)
 
87
{
 
88
        return keyctl(KEYCTL_JOIN_SESSION_KEYRING, name);
 
89
}
 
90
 
 
91
long keyctl_update(key_serial_t id, const void *payload, size_t plen)
 
92
{
 
93
        return keyctl(KEYCTL_UPDATE, id, payload, plen);
 
94
}
 
95
 
 
96
long keyctl_revoke(key_serial_t id)
 
97
{
 
98
        return keyctl(KEYCTL_REVOKE, id);
 
99
}
 
100
 
 
101
long keyctl_chown(key_serial_t id, uid_t uid, gid_t gid)
 
102
{
 
103
        return keyctl(KEYCTL_CHOWN, id, uid, gid);
 
104
}
 
105
 
 
106
long keyctl_setperm(key_serial_t id, key_perm_t perm)
 
107
{
 
108
        return keyctl(KEYCTL_SETPERM, id, perm);
 
109
}
 
110
 
 
111
long keyctl_describe(key_serial_t id, char *buffer, size_t buflen)
 
112
{
 
113
        return keyctl(KEYCTL_DESCRIBE, id, buffer, buflen);
 
114
}
 
115
 
 
116
long keyctl_clear(key_serial_t ringid)
 
117
{
 
118
        return keyctl(KEYCTL_CLEAR, ringid);
 
119
}
 
120
 
 
121
long keyctl_link(key_serial_t id, key_serial_t ringid)
 
122
{
 
123
        return keyctl(KEYCTL_LINK, id, ringid);
 
124
}
 
125
 
 
126
long keyctl_unlink(key_serial_t id, key_serial_t ringid)
 
127
{
 
128
        return keyctl(KEYCTL_UNLINK, id, ringid);
 
129
}
 
130
 
 
131
long keyctl_search(key_serial_t ringid,
 
132
                   const char *type,
 
133
                   const char *description,
 
134
                   key_serial_t destringid)
 
135
{
 
136
        return keyctl(KEYCTL_SEARCH, ringid, type, description, destringid);
 
137
}
 
138
 
 
139
long keyctl_read(key_serial_t id, char *buffer, size_t buflen)
 
140
{
 
141
        return keyctl(KEYCTL_READ, id, buffer, buflen);
 
142
}
 
143
 
 
144
long keyctl_instantiate(key_serial_t id,
 
145
                        const void *payload,
 
146
                        size_t plen,
 
147
                        key_serial_t ringid)
 
148
{
 
149
        return keyctl(KEYCTL_INSTANTIATE, id, payload, plen, ringid);
 
150
}
 
151
 
 
152
long keyctl_negate(key_serial_t id, unsigned timeout, key_serial_t ringid)
 
153
{
 
154
        return keyctl(KEYCTL_NEGATE, id, timeout, ringid);
 
155
}
 
156
 
 
157
long keyctl_set_reqkey_keyring(int reqkey_defl)
 
158
{
 
159
        return keyctl(KEYCTL_SET_REQKEY_KEYRING, reqkey_defl);
 
160
}
 
161
 
 
162
long keyctl_set_timeout(key_serial_t id, unsigned timeout)
 
163
{
 
164
        return keyctl(KEYCTL_SET_TIMEOUT, id, timeout);
 
165
}
 
166
 
 
167
long keyctl_assume_authority(key_serial_t id)
 
168
{
 
169
        return keyctl(KEYCTL_ASSUME_AUTHORITY, id);
 
170
}
 
171
 
 
172
long keyctl_get_security(key_serial_t id, char *buffer, size_t buflen)
 
173
{
 
174
        return keyctl(KEYCTL_GET_SECURITY, id, buffer, buflen);
 
175
}
 
176
 
 
177
long keyctl_session_to_parent(void)
 
178
{
 
179
        return keyctl(KEYCTL_SESSION_TO_PARENT);
 
180
}
 
181
 
 
182
long keyctl_reject(key_serial_t id, unsigned timeout, unsigned error,
 
183
                   key_serial_t ringid)
 
184
{
 
185
        long ret = keyctl(KEYCTL_REJECT, id, timeout, error, ringid);
 
186
 
 
187
        /* fall back to keyctl_negate() if this op is not supported by this
 
188
         * kernel version */
 
189
        if (ret == -1 && errno == EOPNOTSUPP)
 
190
                return keyctl_negate(id, timeout, ringid);
 
191
        return ret;
 
192
}
 
193
 
 
194
long keyctl_instantiate_iov(key_serial_t id,
 
195
                            const struct iovec *payload_iov,
 
196
                            unsigned ioc,
 
197
                            key_serial_t ringid)
 
198
{
 
199
        long ret = keyctl(KEYCTL_INSTANTIATE_IOV, id, payload_iov, ioc, ringid);
 
200
 
 
201
        /* fall back to keyctl_instantiate() if this op is not supported by
 
202
         * this kernel version */
 
203
        if (ret == -1 && errno == EOPNOTSUPP) {
 
204
                unsigned loop;
 
205
                size_t bsize = 0, seg;
 
206
                void *buf, *p;
 
207
 
 
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;
 
212
                if (bsize == 0)
 
213
                        return keyctl_instantiate(id, NULL, 0, ringid);
 
214
                p = buf = malloc(bsize);
 
215
                if (!buf)
 
216
                        return -1;
 
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;
 
220
                }
 
221
                ret = keyctl_instantiate(id, buf, bsize, ringid);
 
222
                free(buf);
 
223
        }
 
224
        return ret;
 
225
}
 
226
 
 
227
 
 
228
/*****************************************************************************/
 
229
/*
 
230
 * plain realloc is just crazy
 
231
 */
 
232
static void* __xrealloc(void* ptr, size_t size)
 
233
{
 
234
    void* ret;
 
235
 
 
236
    ret = realloc(ptr, size);
 
237
    if(!ret) {
 
238
        free(ptr);
 
239
        return 0;
 
240
    }
 
241
    return ret;
 
242
}
 
243
 
 
244
 
 
245
/*****************************************************************************/
 
246
/*
 
247
 * fetch key description into an allocated buffer
 
248
 * - resulting string is NUL terminated
 
249
 * - returns count not including NUL
 
250
 */
 
251
int keyctl_describe_alloc(key_serial_t id, char **_buffer)
 
252
{
 
253
        char *buf;
 
254
        long buflen, ret;
 
255
 
 
256
        ret = keyctl_describe(id, NULL, 0);
 
257
        if (ret < 0)
 
258
                return -1;
 
259
 
 
260
        buflen = ret;
 
261
        buf = malloc(buflen);
 
262
        if (!buf)
 
263
                return -1;
 
264
 
 
265
        for (;;) {
 
266
                ret = keyctl_describe(id, buf, buflen);
 
267
                if (ret < 0)
 
268
                        return -1;
 
269
 
 
270
                if (buflen >= ret)
 
271
                        break;
 
272
 
 
273
                buflen = ret;
 
274
                buf = __xrealloc(buf, buflen);
 
275
                if (!buf)
 
276
                        return -1;
 
277
        }
 
278
 
 
279
        *_buffer = buf;
 
280
        return buflen - 1;
 
281
 
 
282
} /* end keyctl_describe_alloc() */
 
283
 
 
284
/*****************************************************************************/
 
285
/*
 
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)
 
289
 */
 
290
int keyctl_read_alloc(key_serial_t id, void **_buffer)
 
291
{
 
292
        void *buf;
 
293
        long buflen, ret;
 
294
 
 
295
        ret = keyctl_read(id, NULL, 0);
 
296
        if (ret < 0)
 
297
                return -1;
 
298
 
 
299
        buflen = ret;
 
300
        buf = malloc(buflen + 1);
 
301
        if (!buf)
 
302
                return -1;
 
303
 
 
304
        for (;;) {
 
305
                ret = keyctl_read(id, buf, buflen);
 
306
                if (ret < 0)
 
307
                        return -1;
 
308
 
 
309
                if (buflen >= ret)
 
310
                        break;
 
311
 
 
312
                buflen = ret;
 
313
                buf = __xrealloc(buf, buflen + 1);
 
314
                if (!buf)
 
315
                        return -1;
 
316
        }
 
317
 
 
318
        ((unsigned char *) buf)[buflen] = 0;
 
319
        *_buffer = buf;
 
320
        return buflen;
 
321
 
 
322
} /* end keyctl_read_alloc() */
 
323
 
 
324
/*****************************************************************************/
 
325
/*
 
326
 * fetch key security label into an allocated buffer
 
327
 * - resulting string is NUL terminated
 
328
 * - returns count not including NUL
 
329
 */
 
330
int keyctl_get_security_alloc(key_serial_t id, char **_buffer)
 
331
{
 
332
        char *buf;
 
333
        long buflen, ret;
 
334
 
 
335
        ret = keyctl_get_security(id, NULL, 0);
 
336
        if (ret < 0)
 
337
                return -1;
 
338
 
 
339
        buflen = ret;
 
340
        buf = malloc(buflen);
 
341
        if (!buf)
 
342
                return -1;
 
343
 
 
344
        for (;;) {
 
345
                ret = keyctl_get_security(id, buf, buflen);
 
346
                if (ret < 0)
 
347
                        return -1;
 
348
 
 
349
                if (buflen >= ret)
 
350
                        break;
 
351
 
 
352
                buflen = ret;
 
353
                buf = realloc(buf, buflen);
 
354
                if (!buf)
 
355
                        return -1;
 
356
        }
 
357
 
 
358
        *_buffer = buf;
 
359
        return buflen - 1;
 
360
}
 
361
 
 
362
/*
 
363
 * Depth-first recursively apply a function over a keyring tree
 
364
 */
 
365
static int recursive_key_scan_aux(key_serial_t parent, key_serial_t key,
 
366
                                  int depth, recursive_key_scanner_t func,
 
367
                                  void *data)
 
368
{
 
369
        key_serial_t *pk;
 
370
        key_perm_t perm;
 
371
        size_t ringlen;
 
372
        void *ring;
 
373
        char *desc, type[255];
 
374
        int desc_len, uid, gid, ret, n, kcount = 0;
 
375
 
 
376
        if (depth > 800)
 
377
                return 0;
 
378
 
 
379
        /* read the key description */
 
380
        desc = NULL;
 
381
        desc_len = keyctl_describe_alloc(key, &desc);
 
382
        if (desc_len < 0)
 
383
                goto do_this_key;
 
384
 
 
385
        /* parse */
 
386
        type[0] = 0;
 
387
 
 
388
        n = sscanf(desc, "%[^;];%d;%d;%x;", type, &uid, &gid, &perm);
 
389
        if (n != 4) {
 
390
                free(desc);
 
391
                desc = NULL;
 
392
                errno = -EINVAL;
 
393
                desc_len = -1;
 
394
                goto do_this_key;
 
395
        }
 
396
 
 
397
        /* if it's a keyring then we're going to want to recursively search it
 
398
         * if we can */
 
399
        if (strcmp(type, "keyring") == 0) {
 
400
                /* read the keyring's contents */
 
401
                ret = keyctl_read_alloc(key, &ring);
 
402
                if (ret < 0)
 
403
                        goto do_this_key;
 
404
 
 
405
                ringlen = ret;
 
406
 
 
407
                /* walk the keyring */
 
408
                pk = ring;
 
409
                for (ringlen = ret;
 
410
                     ringlen >= sizeof(key_serial_t);
 
411
                     ringlen -= sizeof(key_serial_t)
 
412
                     )
 
413
                        kcount += recursive_key_scan_aux(key, *pk++, depth + 1,
 
414
                                                         func, data);
 
415
 
 
416
                free(ring);
 
417
        }
 
418
 
 
419
do_this_key:
 
420
        kcount += func(parent, key, desc, desc_len, data);
 
421
        free(desc);
 
422
        return kcount;
 
423
}
 
424
 
 
425
/*
 
426
 * Depth-first apply a function over a keyring tree
 
427
 */
 
428
int recursive_key_scan(key_serial_t key, recursive_key_scanner_t func, void *data)
 
429
{
 
430
        return recursive_key_scan_aux(0, key, 0, func, data);
 
431
}
 
432
 
 
433
/*
 
434
 * Depth-first apply a function over session keyring tree
 
435
 */
 
436
int recursive_session_key_scan(recursive_key_scanner_t func, void *data)
 
437
{
 
438
        key_serial_t session =
 
439
                keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 0);
 
440
        if (session > 0)
 
441
                return recursive_key_scan(session, func, data);
 
442
        return 0;
 
443
}
 
444
 
 
445
#ifdef NO_GLIBC_KEYERR
 
446
/*****************************************************************************/
 
447
/*
 
448
 * initialise error handling
 
449
 */
 
450
static void error_init(void)
 
451
{
 
452
        char *err;
 
453
 
 
454
        error_inited = 1;
 
455
 
 
456
        dlerror();
 
457
 
 
458
        libc_perror = dlsym(RTLD_NEXT,"perror");
 
459
        if (!libc_perror) {
 
460
                fprintf(stderr, "Failed to look up next perror\n");
 
461
                err = dlerror();
 
462
                if (err)
 
463
                        fprintf(stderr, "%s\n", err);
 
464
                abort();
 
465
        }
 
466
 
 
467
        //fprintf(stderr, "next perror at %p\n", libc_perror);
 
468
 
 
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");
 
472
                err = dlerror();
 
473
                if (err)
 
474
                        fprintf(stderr, "%s\n", err);
 
475
                abort();
 
476
        }
 
477
 
 
478
        //fprintf(stderr, "next strerror_r at %p\n", libc_strerror_r);
 
479
 
 
480
#if 0
 
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");
 
484
                err = dlerror();
 
485
                if (err)
 
486
                        fprintf(stderr, "%s\n", err);
 
487
                abort();
 
488
        }
 
489
 
 
490
        //fprintf(stderr, "next xpg_strerror_r at %p\n", libc_xpg_strerror_r);
 
491
#endif
 
492
 
 
493
} /* end error_init() */
 
494
 
 
495
/*****************************************************************************/
 
496
/*
 
497
 * overload glibc's strerror_r() with a version that knows about key errors
 
498
 */
 
499
char *strerror_r(int errnum, char *buf, size_t n)
 
500
{
 
501
        const char *errstr;
 
502
        int len;
 
503
 
 
504
        printf("hello\n");
 
505
 
 
506
        if (!error_inited)
 
507
                error_init();
 
508
 
 
509
        switch (errnum) {
 
510
        case ENOKEY:
 
511
                errstr = "Requested key not available";
 
512
                break;
 
513
 
 
514
        case EKEYEXPIRED:
 
515
                errstr = "Key has expired";
 
516
                break;
 
517
 
 
518
        case EKEYREVOKED:
 
519
                errstr = "Key has been revoked";
 
520
                break;
 
521
 
 
522
        case EKEYREJECTED:
 
523
                errstr = "Key was rejected by service";
 
524
                break;
 
525
 
 
526
        default:
 
527
                return libc_strerror_r(errnum, buf, n);
 
528
        }
 
529
 
 
530
        len = strlen(errstr) + 1;
 
531
        if (n > len) {
 
532
                errno = ERANGE;
 
533
                if (n > 0) {
 
534
                        memcpy(buf, errstr, n - 1);
 
535
                        buf[n - 1] = 0;
 
536
                }
 
537
                return NULL;
 
538
        }
 
539
        else {
 
540
                memcpy(buf, errstr, len);
 
541
                return buf;
 
542
        }
 
543
 
 
544
} /* end strerror_r() */
 
545
 
 
546
#if 0
 
547
/*****************************************************************************/
 
548
/*
 
549
 * overload glibc's strerror_r() with a version that knows about key errors
 
550
 */
 
551
int xpg_strerror_r(int errnum, char *buf, size_t n)
 
552
{
 
553
        const char *errstr;
 
554
        int len;
 
555
 
 
556
        if (!error_inited)
 
557
                error_init();
 
558
 
 
559
        switch (errnum) {
 
560
        case ENOKEY:
 
561
                errstr = "Requested key not available";
 
562
                break;
 
563
 
 
564
        case EKEYEXPIRED:
 
565
                errstr = "Key has expired";
 
566
                break;
 
567
 
 
568
        case EKEYREVOKED:
 
569
                errstr = "Key has been revoked";
 
570
                break;
 
571
 
 
572
        case EKEYREJECTED:
 
573
                errstr = "Key was rejected by service";
 
574
                break;
 
575
 
 
576
        default:
 
577
                return libc_xpg_strerror_r(errnum, buf, n);
 
578
        }
 
579
 
 
580
        len = strlen(errstr) + 1;
 
581
        if (n > len) {
 
582
                errno = ERANGE;
 
583
                if (n > 0) {
 
584
                        memcpy(buf, errstr, n - 1);
 
585
                        buf[n - 1] = 0;
 
586
                }
 
587
                return -1;
 
588
        }
 
589
        else {
 
590
                memcpy(buf, errstr, len);
 
591
                return 0;
 
592
        }
 
593
 
 
594
} /* end xpg_strerror_r() */
 
595
#endif
 
596
 
 
597
/*****************************************************************************/
 
598
/*
 
599
 *
 
600
 */
 
601
void perror(const char *msg)
 
602
{
 
603
        if (!error_inited)
 
604
                error_init();
 
605
 
 
606
        switch (errno) {
 
607
        case ENOKEY:
 
608
                fprintf(stderr, "%s: Requested key not available\n", msg);
 
609
                return;
 
610
 
 
611
        case EKEYEXPIRED:
 
612
                fprintf(stderr, "%s: Key has expired\n", msg);
 
613
                return;
 
614
 
 
615
        case EKEYREVOKED:
 
616
                fprintf(stderr, "%s: Key has been revoked\n", msg);
 
617
                return;
 
618
 
 
619
        case EKEYREJECTED:
 
620
                fprintf(stderr, "%s: Key was rejected by service\n", msg);
 
621
                return;
 
622
 
 
623
        default:
 
624
                libc_perror(msg);
 
625
                return;
 
626
        }
 
627
 
 
628
} /* end perror() */
 
629
#endif