source: trunk/debathena/debathena/libnss-afspag/nss_afspag.c @ 22686

Revision 22686, 3.6 KB checked in by ghudson, 17 years ago (diff)
* debathena/debathena: Snapshot debathena package sources from /mit/debathena/packages/debathena.
Line 
1/*
2 * nss_afspag.c
3 * nsswitch module to assign group names to AFS PAG groups.
4 *
5 * Copyright © 2007 Anders Kaseorg <andersk@mit.edu>
6 *
7 * Permission is hereby granted, free of charge, to any person
8 * obtaining a copy of this software and associated documentation
9 * files (the "Software"), to deal in the Software without
10 * restriction, including without limitation the rights to use, copy,
11 * modify, merge, publish, distribute, sublicense, and/or sell copies
12 * of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
22 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 */
27
28#include <sys/types.h>
29#include <unistd.h>
30#include <stdlib.h>
31#include <stdint.h>
32#include <grp.h>
33#include <nss.h>
34#include <string.h>
35#include <stdio.h>
36#include <errno.h>
37
38static enum nss_status
39getfakegr_r(gid_t gid, struct group *grp, char *buffer, size_t buflen, int *errnop)
40{
41    int n;
42   
43    n = snprintf(buffer, buflen, "afspag-%d", gid);
44    if (n < 0 || n >= buflen)
45        goto erange;
46    grp->gr_name = buffer;
47    buffer += n + 1;
48    buflen -= n + 1;
49
50    n = snprintf(buffer, buflen, "x");
51    if (n < 0 || n >= buflen)
52        goto erange;
53    grp->gr_passwd = buffer;
54    buffer += n + 1;
55    buflen -= n + 1;
56
57    grp->gr_gid = gid;
58
59    if (buflen < sizeof((char *)0))
60        goto erange;
61    grp->gr_mem = (char **)buffer;
62    *grp->gr_mem = NULL;
63    buffer += sizeof((char *)0);
64    buflen -= sizeof((char *)0);
65
66    return NSS_STATUS_SUCCESS;
67 erange:
68    *errnop = ERANGE;
69    return NSS_STATUS_TRYAGAIN;
70}
71
72enum nss_status
73_nss_afspag_getgrgid_r(gid_t gid, struct group *grp,
74                       char *buffer, size_t buflen, int *errnop)
75{
76    gid_t *gids = NULL, *pgid;
77    int ngids = getgroups(0, gids);
78    if (ngids == -1) {
79        *errnop = EINVAL;
80        return NSS_STATUS_TRYAGAIN;
81    }
82    gids = malloc(ngids * sizeof(gid_t));
83    if (gids == NULL) {
84        *errnop = ENOMEM;
85        return NSS_STATUS_TRYAGAIN;
86    }
87    ngids = getgroups(ngids, gids);
88    if (ngids == -1) {
89        free(gids);
90        *errnop = EINVAL;
91        return NSS_STATUS_TRYAGAIN;
92    }
93
94    /* See openafs/src/afs/afs_osi_pag.c. */
95    for (pgid = gids; pgid < gids + ngids; pgid++)
96        if (*pgid == gid && ((gid >> 24) & 0xff) == 'A') {
97            free(gids);
98            return getfakegr_r(gid, grp, buffer, buflen, errnop);
99        }
100
101    if ((gid == gids[0] || gid == gids[1])) {
102        uint32_t g0 = gids[0], g1 = gids[1];
103        free(gids);
104        g0 -= 0x3f00;
105        g1 -= 0x3f00;
106        if (g0 < 0xc000 && g1 < 0xc000) {
107            uint32_t l = ((g0 & 0x3fff) << 14) | (g1 & 0x3fff);
108            uint32_t h = (g1 >> 14) + 3*(g0 >> 14);
109            uint32_t ret = ((h << 28) | l);
110            if (((ret >> 24) & 0xff) == 'A')
111                return getfakegr_r(gid, grp, buffer, buflen, errnop);
112        }
113    } else {
114        free(gids);
115    }
116
117    return NSS_STATUS_NOTFOUND;
118}
119
120enum nss_status
121_nss_afspag_getgrnam_r(const char *name, struct group *grp,
122                       char *buffer, size_t buflen, int *errnop)
123{
124    unsigned int gid;
125    int n;
126    if (strncmp(name, "afspag-", 7) == 0 &&
127        sscanf(name + 7, "%u%n", &gid, &n) >= 1 &&
128        n == strlen(name + 7))
129        return _nss_afspag_getgrgid_r((gid_t)gid, grp, buffer, buflen, errnop);
130    return NSS_STATUS_NOTFOUND;
131}
Note: See TracBrowser for help on using the repository browser.