]> arthur.barton.de Git - netatalk.git/blob - libatalk/acl/uuid.c
Fix for #3074076, symlinks with EAs and ACLs
[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
24 #include <atalk/logger.h>
25 #include <atalk/afp.h>
26 #include <atalk/uuid.h>
27
28 #include "aclldap.h"
29 #include "cache.h"
30
31 char *uuidtype[] = {"NULL","USER", "GROUP"};
32
33 /********************************************************
34  * Public helper function
35  ********************************************************/
36
37 /* 
38  * convert ascii string that can include dashes to binary uuid.
39  * caller must provide a buffer.
40  */
41 void uuid_string2bin( const char *uuidstring, uuidp_t uuid) {
42     int nibble = 1;
43     int i = 0;
44     unsigned char c, val = 0;
45
46     while (*uuidstring) {
47         c = *uuidstring;
48         if (c == '-') {
49             uuidstring++;
50             continue;
51         }
52         else if (c <= '9')      /* 0-9 */
53             c -= '0';
54         else if (c <= 'F')  /* A-F */
55             c -= 'A' - 10;
56         else if (c <= 'f')      /* a-f */
57             c-= 'a' - 10;
58
59         if (nibble)
60             val = c * 16;
61         else
62             uuid[i++] = val + c;
63
64         nibble ^= 1;
65         uuidstring++;
66     }
67
68 }
69
70 /* 
71  * convert 16 byte binary uuid to neat ascii represantation including dashes
72  * string is allocated and pointer returned. caller must freee.
73  */
74 int uuid_bin2string( uuidp_t uuid, char **uuidstring) {
75     char ascii[16] = { "0123456789ABCDEF" };
76     int nibble = 1;
77     int i = 0;
78     unsigned char c;
79     char *s;
80
81     *uuidstring = calloc(1, UUID_STRINGSIZE + 1);
82     if (*uuidstring == NULL) {
83         LOG(log_error, logtype_default, "uuid_bin2string: %s: error calloc'ing",strerror(errno));
84         return -1;
85     }
86     s = *uuidstring;
87
88     while (i < UUID_STRINGSIZE) {
89         c = *uuid;
90         if (nibble)
91             c = c >> 4;
92         else {
93             c &= 0x0f;
94             uuid++;
95         }
96         s[i] = ascii[c];
97         nibble ^= 1;
98         i++;
99         if (i==8 || i==13 || i==18 || i==23)
100             s[i++] = '-';
101     }
102     return 0;
103 }
104
105 /********************************************************
106  * Interface
107  ********************************************************/
108
109 /*
110  *   name: give me his name
111  *   type: and type (UUID_USER or UUID_GROUP)
112  *   uuid: pointer to uuid_t storage that the caller must provide
113  * returns 0 on success !=0 on errror
114  */  
115 int getuuidfromname( const char *name, uuidtype_t type, uuidp_t uuid) {
116     int ret = 0;
117     char *uuid_string = NULL;
118
119     ret = search_cachebyname( name, type, uuid);
120     if (ret == 0) {     /* found in cache */
121 #ifdef DEBUG
122         uuid_bin2string( uuid, &uuid_string);
123         LOG(log_debug, logtype_afpd, "getuuidfromname{cache}: name: %s, type: %s -> UUID: %s",
124             name, uuidtype[type], uuid_string);
125 #else
126         LOG(log_debug, logtype_afpd, "getuuidfromname{cache}: name: %s, type: %s",
127             name, uuidtype[type]);
128 #endif
129     } else  {                   /* if not found in cache */
130         ret = ldap_getuuidfromname( name, type, &uuid_string);
131         if (ret != 0) {
132             LOG(log_info, logtype_afpd, "getuuidfromname: no result from ldap_getuuidfromname");
133             goto cleanup;
134         }
135         uuid_string2bin( uuid_string, uuid);
136         add_cachebyname( name, uuid, type, 0);
137         LOG(log_debug, logtype_afpd, "getuuidfromname{LDAP}: name: %s, type: %s -> UUID: %s",name, uuidtype[type], uuid_string);
138     }
139
140 cleanup:
141     free(uuid_string);
142     return ret;
143 }
144
145 /* 
146  * uuidp: pointer to a uuid
147  * name: returns allocated buffer from ldap_getnamefromuuid
148  * type: returns USER or GROUP
149  * return 0 on success !=0 on errror
150  *
151  * Caller must free name appropiately.
152  */
153 int getnamefromuuid( uuidp_t uuidp, char **name, uuidtype_t *type) {
154     int ret;
155     char *uuid_string = NULL;
156
157     ret = search_cachebyuuid( uuidp, name, type);
158     if (ret == 0) {     /* found in cache */
159 #ifdef DEBUG
160         uuid_bin2string( uuidp, &uuid_string);
161         LOG(log_debug9, logtype_afpd, "getnamefromuuid{cache}: UUID: %s -> name: %s, type:%s", uuid_string, *name, uuidtype[*type]);
162         free(uuid_string);
163         uuid_string = NULL;
164 #endif
165     } else  {                   /* if not found in cache */
166         uuid_bin2string( uuidp, &uuid_string);
167         ret = ldap_getnamefromuuid( uuid_string, name, type);
168         if (ret != 0) {
169             LOG(log_error, logtype_afpd, "getnamefromuuid: no result from ldap_getnamefromuuid");
170             goto cleanup;
171         }
172         add_cachebyuuid( uuidp, *name, *type, 0);
173         LOG(log_debug, logtype_afpd, "getnamefromuuid{LDAP}: UUID: %s -> name: %s, type:%s",uuid_string, *name, uuidtype[*type]);
174     }
175
176 cleanup:
177     free(uuid_string);
178     return ret;
179 }