]> arthur.barton.de Git - netatalk.git/blob - libatalk/acl/uuid.c
Convert uuid_bin2string to not allocate but return pointer to static string
[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  * 
75  * Returns pointer to static buffer.
76  */
77 const char *uuid_bin2string(char *uuid) {
78     static char uuidstring[UUID_STRINGSIZE + 1];
79     char ascii[16] = { "0123456789ABCDEF" };
80     int nibble = 1;
81     int i = 0;
82     int c;
83     
84     while (i < UUID_STRINGSIZE) {
85         c = *uuid;
86         if (nibble)
87             c = c >> 4;
88         else {
89             c &= 0x0f;
90             uuid++;
91         }
92         uuidstring[i] = ascii[c];
93         nibble ^= 1;
94         i++;
95         if (i==8 || i==13 || i==18 || i==23)
96             uuidstring[i++] = '-';
97     }
98     uuidstring[i] = 0;
99     return uuidstring;
100 }
101
102 /********************************************************
103  * Interface
104  ********************************************************/
105
106 /*
107  *   name: give me his name
108  *   type: and type (UUID_USER or UUID_GROUP)
109  *   uuid: pointer to uuid_t storage that the caller must provide
110  * returns 0 on success !=0 on errror
111  */  
112 int getuuidfromname( const char *name, uuidtype_t type, uuidp_t uuid) {
113     int ret = 0;
114     char *uuid_string = NULL;
115
116     ret = search_cachebyname( name, type, uuid);
117     if (ret == 0) {
118         /* found in cache */
119         LOG(log_debug, logtype_afpd, "getuuidfromname{cache}: name: %s, type: %s -> UUID: %s",
120             name, uuidtype[type], uuid_bin2string(uuid));
121     } else  {
122         /* if not found in cache */
123         ret = ldap_getuuidfromname( name, type, &uuid_string);
124         if (ret != 0) {
125             LOG(log_note, logtype_afpd, "getuuidfromname(\"%s\",t:%u): no result from ldap search",
126                 name, type);
127             goto cleanup;
128         }
129         uuid_string2bin( uuid_string, uuid);
130         add_cachebyname( name, uuid, type, 0);
131         LOG(log_debug, logtype_afpd, "getuuidfromname{LDAP}: name: %s, type: %s -> UUID: %s",name, uuidtype[type], uuid_string);
132     }
133
134 cleanup:
135     if (uuid_string) free(uuid_string);
136     return ret;
137 }
138
139 static char local_group_uuid[] = {0xab, 0xcd, 0xef,
140                                   0xab, 0xcd, 0xef,
141                                   0xab, 0xcd, 0xef, 
142                                   0xab, 0xcd, 0xef};
143
144 static char local_user_uuid[] = {0xff, 0xff, 0xee, 0xee, 0xdd, 0xdd,
145                                  0xcc, 0xcc, 0xbb, 0xbb, 0xaa, 0xaa};
146
147 /*
148  * uuidp: pointer to a uuid
149  * name: returns allocated buffer from ldap_getnamefromuuid
150  * type: returns USER, GROUP or LOCAL
151  * return 0 on success !=0 on errror
152  *
153  * Caller must free name appropiately.
154  */
155 int getnamefromuuid(const uuidp_t uuidp, char **name, uuidtype_t *type) {
156     int ret;
157
158     ret = search_cachebyuuid( uuidp, name, type);
159     if (ret == 0) {
160         /* found in cache */
161         LOG(log_debug9, logtype_afpd, "getnamefromuuid{cache}: UUID: %s -> name: %s, type:%s",
162             uuid_bin2string(uuidp), *name, uuidtype[*type]);
163     } else {
164         /* not found in cache */
165
166         /* Check if UUID is a client local one */
167         if (memcmp(uuidp, local_user_uuid, 12) == 0
168             || memcmp(uuidp, local_group_uuid, 12) == 0) {
169             LOG(log_debug, logtype_afpd, "getnamefromuuid: local UUID: %" PRIu32 "",
170                 ntohl(*(uint32_t *)(uuidp + 12)));
171             *type = UUID_LOCAL;
172             *name = strdup("UUID_LOCAL");
173             return 0;
174         }
175
176         ret = ldap_getnamefromuuid(uuid_bin2string(uuidp), name, type);
177         if (ret != 0) {
178             LOG(log_warning, logtype_afpd, "getnamefromuuid(%s): no result from ldap_getnamefromuuid",
179                 uuid_bin2string(uuidp));
180             goto cleanup;
181         }
182         add_cachebyuuid( uuidp, *name, *type, 0);
183         LOG(log_debug, logtype_afpd, "getnamefromuuid{LDAP}: UUID: %s -> name: %s, type:%s",
184             uuid_bin2string(uuidp), *name, uuidtype[*type]);
185     }
186
187 cleanup:
188     return ret;
189 }