]> arthur.barton.de Git - netatalk.git/blob - libatalk/acl/uuid.c
Merge branch-2-1
[netatalk.git] / libatalk / acl / uuid.c
1 /*
2   Copyright (c) 2008,2009 Frank Lahm <franklahm@gmail.com>
3
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU General Public License as published by
6   the Free Software Foundation; either version 2 of the License, or
7   (at your option) any later version.
8
9   This program is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   GNU General Public License for more details.
13 */
14
15 #ifdef HAVE_CONFIG_H
16 #include "config.h"
17 #endif /* HAVE_CONFIG_H */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <inttypes.h>
24
25 #include <atalk/logger.h>
26 #include <atalk/afp.h>
27 #include <atalk/uuid.h>
28 #include <atalk/util.h>
29
30 #include "aclldap.h"
31 #include "cache.h"
32
33 char *uuidtype[] = {"NULL","USER", "GROUP", "LOCAL"};
34
35 /********************************************************
36  * Public helper function
37  ********************************************************/
38
39 /* 
40  * convert ascii string that can include dashes to binary uuid.
41  * caller must provide a buffer.
42  */
43 void uuid_string2bin( const char *uuidstring, uuidp_t uuid) {
44     int nibble = 1;
45     int i = 0;
46     unsigned char c, val = 0;
47
48     while (*uuidstring) {
49         c = *uuidstring;
50         if (c == '-') {
51             uuidstring++;
52             continue;
53         }
54         else if (c <= '9')      /* 0-9 */
55             c -= '0';
56         else if (c <= 'F')  /* A-F */
57             c -= 'A' - 10;
58         else if (c <= 'f')      /* a-f */
59             c-= 'a' - 10;
60
61         if (nibble)
62             val = c * 16;
63         else
64             uuid[i++] = val + c;
65
66         nibble ^= 1;
67         uuidstring++;
68     }
69
70 }
71
72 /* 
73  * convert 16 byte binary uuid to neat ascii represantation including dashes
74  * string is allocated and pointer returned. caller must freee.
75  */
76 int uuid_bin2string( uuidp_t uuid, char **uuidstring) {
77     char ascii[16] = { "0123456789ABCDEF" };
78     int nibble = 1;
79     int i = 0;
80     unsigned char c;
81     char *s;
82
83     *uuidstring = calloc(1, UUID_STRINGSIZE + 1);
84     if (*uuidstring == NULL) {
85         LOG(log_error, logtype_default, "uuid_bin2string: %s: error calloc'ing",strerror(errno));
86         return -1;
87     }
88     s = *uuidstring;
89
90     while (i < UUID_STRINGSIZE) {
91         c = *uuid;
92         if (nibble)
93             c = c >> 4;
94         else {
95             c &= 0x0f;
96             uuid++;
97         }
98         s[i] = ascii[c];
99         nibble ^= 1;
100         i++;
101         if (i==8 || i==13 || i==18 || i==23)
102             s[i++] = '-';
103     }
104     return 0;
105 }
106
107 /********************************************************
108  * Interface
109  ********************************************************/
110
111 /*
112  *   name: give me his name
113  *   type: and type (UUID_USER or UUID_GROUP)
114  *   uuid: pointer to uuid_t storage that the caller must provide
115  * returns 0 on success !=0 on errror
116  */  
117 int getuuidfromname( const char *name, uuidtype_t type, uuidp_t uuid) {
118     int ret = 0;
119     char *uuid_string = NULL;
120
121     ret = search_cachebyname( name, type, uuid);
122     if (ret == 0) {     /* found in cache */
123 #ifdef DEBUG
124         uuid_bin2string( uuid, &uuid_string);
125         LOG(log_debug, logtype_afpd, "getuuidfromname{cache}: name: %s, type: %s -> UUID: %s",
126             name, uuidtype[type], uuid_string);
127 #else
128         LOG(log_debug, logtype_afpd, "getuuidfromname{cache}: name: %s, type: %s",
129             name, uuidtype[type]);
130 #endif
131     } else  {                   /* if not found in cache */
132         ret = ldap_getuuidfromname( name, type, &uuid_string);
133         if (ret != 0) {
134             LOG(log_note, logtype_afpd, "getuuidfromname(\"%s\",t:%u): no result from ldap search",
135                 name, type);
136             goto cleanup;
137         }
138         uuid_string2bin( uuid_string, uuid);
139         add_cachebyname( name, uuid, type, 0);
140         LOG(log_debug, logtype_afpd, "getuuidfromname{LDAP}: name: %s, type: %s -> UUID: %s",name, uuidtype[type], uuid_string);
141     }
142
143 cleanup:
144     free(uuid_string);
145     return ret;
146 }
147
148 static char local_group_uuid[] = {0xab, 0xcd, 0xef,
149                                   0xab, 0xcd, 0xef,
150                                   0xab, 0xcd, 0xef, 
151                                   0xab, 0xcd, 0xef};
152
153 static char local_user_uuid[] = {0xff, 0xff, 0xee, 0xee, 0xdd, 0xdd,
154                                  0xcc, 0xcc, 0xbb, 0xbb, 0xaa, 0xaa};
155
156 /*
157  * uuidp: pointer to a uuid
158  * name: returns allocated buffer from ldap_getnamefromuuid
159  * type: returns USER, GROUP or LOCAL
160  * return 0 on success !=0 on errror
161  *
162  * Caller must free name appropiately.
163  */
164 int getnamefromuuid(const uuidp_t uuidp, char **name, uuidtype_t *type) {
165     int ret;
166     char *uuid_string = NULL;
167
168     ret = search_cachebyuuid( uuidp, name, type);
169     if (ret == 0) {     /* found in cache */
170 #ifdef DEBUG
171         uuid_bin2string( uuidp, &uuid_string);
172         LOG(log_debug9, logtype_afpd, "getnamefromuuid{cache}: UUID: %s -> name: %s, type:%s",
173             uuid_string, *name, uuidtype[*type]);
174         free(uuid_string);
175         uuid_string = NULL;
176 #endif
177     } else  {                   /* if not found in cache */
178
179         /* Check if UUID is a client local one */
180         if (memcmp(uuidp, local_user_uuid, 12) == 0
181             || memcmp(uuidp, local_group_uuid, 12) == 0) {
182             LOG(log_debug, logtype_afpd, "getnamefromuuid: local UUID: %" PRIu32 "",
183                 ntohl(*(uint32_t *)(uuidp + 12)));
184             *type = UUID_LOCAL;
185             *name = strdup("UUID_LOCAL");
186             return 0;
187         }
188
189         uuid_bin2string( uuidp, &uuid_string);
190         ret = ldap_getnamefromuuid( uuid_string, name, type);
191         if (ret != 0) {
192             LOG(log_warning, logtype_afpd, "getnamefromuuid(%s): no result from ldap_getnamefromuuid",
193                 uuid_string);
194             goto cleanup;
195         }
196         add_cachebyuuid( uuidp, *name, *type, 0);
197         LOG(log_debug, logtype_afpd, "getnamefromuuid{LDAP}: UUID: %s -> name: %s, type:%s",
198             uuid_string, *name, uuidtype[*type]);
199     }
200
201 cleanup:
202     free(uuid_string);
203     return ret;
204 }