ReactOS  0.4.14-dev-49-gfb4591c
idmap.c
Go to the documentation of this file.
1 /* NFSv4.1 client for Windows
2  * Copyright 2012 The Regents of the University of Michigan
3  *
4  * Olga Kornievskaia <aglo@umich.edu>
5  * Casey Bodley <cbodley@umich.edu>
6  *
7  * This library is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as published by
9  * the Free Software Foundation; either version 2.1 of the License, or (at
10  * your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful, but
13  * without any warranty; without even the implied warranty of merchantability
14  * or fitness for a particular purpose. See the GNU Lesser General Public
15  * License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this library; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20  */
21 
22 #include <windows.h>
23 #include <strsafe.h>
24 #include <winldap.h>
25 #include <stdlib.h> /* for strtoul() */
26 #include <errno.h>
27 #include <time.h>
28 
29 #include "idmap.h"
30 #include "nfs41_const.h"
31 #include "list.h"
32 #include "daemon_debug.h"
33 
34 
35 #define IDLVL 2 /* dprintf level for idmap logging */
36 
37 #define FILTER_LEN 1024
38 #define NAME_LEN 32
39 #define VAL_LEN 257
40 
41 
42 enum ldap_class {
45 
47 };
48 
49 enum ldap_attr {
55 
57 };
58 
59 #define ATTR_FLAG(attr) (1 << (attr))
60 #define ATTR_ISSET(mask, attr) (((mask) & ATTR_FLAG(attr)) != 0)
61 
62 
63 /* ldap/cache lookups */
64 struct idmap_lookup {
67 #ifdef __REACTOS__
68  uint32_t type;
69 #else
71 #endif
73  const void *value;
74 };
75 
76 
77 #ifndef __REACTOS__
78 /* configuration */
79 static const char CONFIG_FILENAME[] = "C:\\ReactOS\\System32\\drivers\\etc\\ms-nfs41-idmap.conf";
80 #endif
81 
82 struct idmap_config {
83  /* ldap server information */
88 
89  /* ldap schema information */
92  char base[VAL_LEN];
93 
94  /* caching configuration */
96 };
97 
98 
102 };
103 
105  const char *key;
106  const char *def;
108  size_t offset;
109  size_t max_len;
110 };
111 
112 /* helper macros for declaring config_options */
113 #define OPT_INT(key,def,field) \
114  { key, def, TYPE_INT, FIELD_OFFSET(struct idmap_config, field), 0 }
115 #define OPT_STR(key,def,field,len) \
116  { key, def, TYPE_STR, FIELD_OFFSET(struct idmap_config, field), len }
117 #define OPT_CLASS(key,def,index) \
118  { key, def, TYPE_STR, FIELD_OFFSET(struct idmap_config, classes[index]), NAME_LEN }
119 #define OPT_ATTR(key,def,index) \
120  { key, def, TYPE_STR, FIELD_OFFSET(struct idmap_config, attributes[index]), NAME_LEN }
121 
122 /* table of recognized config options, including type and default value */
123 static const struct config_option g_options[] = {
124  /* server information */
125  OPT_STR("ldap_hostname", "localhost", hostname, NFS41_HOSTNAME_LEN+1),
126  OPT_INT("ldap_port", "389", port),
127  OPT_INT("ldap_version", "3", version),
128  OPT_INT("ldap_timeout", "0", timeout),
129 
130  /* schema information */
131  OPT_STR("ldap_base", "cn=localhost", base, VAL_LEN),
132  OPT_CLASS("ldap_class_users", "user", CLASS_USER),
133  OPT_CLASS("ldap_class_groups", "group", CLASS_GROUP),
134  OPT_ATTR("ldap_attr_username", "cn", ATTR_USER_NAME),
135  OPT_ATTR("ldap_attr_groupname", "cn", ATTR_GROUP_NAME),
136  OPT_ATTR("ldap_attr_gssAuthName", "gssAuthName", ATTR_PRINCIPAL),
137  OPT_ATTR("ldap_attr_uidNumber", "uidNumber", ATTR_UID),
138  OPT_ATTR("ldap_attr_gidNumber", "gidNumber", ATTR_GID),
139 
140  /* caching configuration */
141  OPT_INT("cache_ttl", "60", cache_ttl),
142 };
143 
144 
145 /* parse each line into key-value pairs
146  * accepts 'key = value' or 'key = "value"',
147  * ignores whitespace anywhere outside the ""s */
148 struct config_pair {
149  const char *key, *value;
151 };
152 
153 static int config_parse_pair(
154  char *line,
155  struct config_pair *pair)
156 {
157  char *pos = line;
158  int status = NO_ERROR;
159 
160  /* terminate at comment */
161  pos = strchr(line, '#');
162  if (pos) *pos = 0;
163 
164  /* skip whitespace before key */
165  pos = line;
166  while (isspace(*pos)) pos++;
167  pair->key = pos;
168 
169  pos = strchr(pos, '=');
170  if (pos == NULL) {
171  eprintf("missing '='\n");
173  goto out;
174  }
175 
176  /* skip whitespace after key */
177  pair->key_len = pos - pair->key;
178  while (pair->key_len && isspace(pair->key[pair->key_len-1]))
179  pair->key_len--;
180 
181  if (pair->key_len <= 0) {
182  eprintf("empty key\n");
184  goto out;
185  }
186 
187  /* skip whitespace after = */
188  pos++;
189  while (isspace(*pos)) pos++;
190 
191  if (*pos == 0) {
192  eprintf("end of line looking for value\n");
194  goto out;
195  }
196 
197  if (*pos == '\"') {
198  /* value is between the "s */
199  pair->value = pos + 1;
200  pos = strchr(pair->value, '\"');
201  if (pos == NULL) {
202  eprintf("no matching '\"'\n");
204  goto out;
205  }
206  pair->value_len = pos - pair->value;
207  } else {
208  pair->value = pos;
209  pair->value_len = strlen(pair->value);
210 
211  /* skip whitespace after value */
212  while (pair->value_len && isspace(pair->value[pair->value_len-1]))
213  pair->value_len--;
214  }
215 
216  /* on success, null terminate the key and value */
217  ((char*)pair->key)[pair->key_len] = 0;
218  ((char*)pair->value)[pair->value_len] = 0;
219 out:
220  return status;
221 }
222 
224  const char *str,
225  UINT *id_out)
226 {
227  PCHAR endp;
228  const UINT id = strtoul(str, &endp, 10);
229 
230  /* must convert the whole string */
231  if ((endp - str) < (ptrdiff_t)strlen(str))
232  return FALSE;
233 
234  /* result must fit in 32 bits */
235  if (id == ULONG_MAX && errno == ERANGE)
236  return FALSE;
237 
238  *id_out = id;
239  return TRUE;
240 }
241 
242 /* parse default values from g_options[] into idmap_config */
243 static int config_defaults(
244  struct idmap_config *config)
245 {
246  const struct config_option *option;
247  const int count = ARRAYSIZE(g_options);
248  char *dst;
249  int i, status = NO_ERROR;
250 
251  for (i = 0; i < count; i++) {
252  option = &g_options[i];
253  dst = (char*)config + option->offset;
254 
255  if (option->type == TYPE_INT) {
256  if (!parse_uint(option->def, (UINT*)dst)) {
258  eprintf("failed to parse default value of %s=\"%s\": "
259  "expected a number\n", option->key, option->def);
260  break;
261  }
262  } else {
263  if (FAILED(StringCchCopyA(dst, option->max_len, option->def))) {
265  eprintf("failed to parse default value of %s=\"%s\": "
266  "buffer overflow > %u\n", option->key, option->def,
267  option->max_len);
268  break;
269  }
270  }
271  }
272  return status;
273 }
274 
276  const struct config_pair *pair,
277  const struct config_option **option)
278 {
279  int i, count = ARRAYSIZE(g_options);
280  int status = ERROR_NOT_FOUND;
281 
282  /* find the config_option by key */
283  for (i = 0; i < count; i++) {
284  if (stricmp(pair->key, g_options[i].key) == 0) {
285  *option = &g_options[i];
286  status = NO_ERROR;
287  break;
288  }
289  }
290  return status;
291 }
292 
293 static int config_load(
294  struct idmap_config *config,
295  const char *filename)
296 {
297  char buffer[1024], *pos;
298  FILE *file;
299  struct config_pair pair;
300  const struct config_option *option;
301  int line = 0;
302  int status = NO_ERROR;
303 
304  /* open the file */
305  file = fopen(filename, "r");
306  if (file == NULL) {
307  eprintf("config_load() failed to open file '%s'\n", filename);
308  goto out;
309  }
310 
311  /* read each line */
312  while (fgets(buffer, sizeof(buffer), file)) {
313  line++;
314 
315  /* skip whitespace */
316  pos = buffer;
317  while (isspace(*pos)) pos++;
318 
319  /* skip comments and empty lines */
320  if (*pos == '#' || *pos == 0)
321  continue;
322 
323  /* parse line into a key=value pair */
325  if (status) {
326  eprintf("error on line %d: %s\n", line, buffer);
327  break;
328  }
329 
330  /* find the config_option by key */
332  if (status) {
333  eprintf("unrecognized option '%s' on line %d: %s\n",
334  pair.key, line, buffer);
336  break;
337  }
338 
339  if (option->type == TYPE_INT) {
340  if (!parse_uint(pair.value, (UINT*)((char*)config + option->offset))) {
342  eprintf("expected a number on line %d: %s=\"%s\"\n",
343  line, pair.key, pair.value);
344  break;
345  }
346  } else {
347  if (FAILED(StringCchCopyNA((char*)config + option->offset,
348  option->max_len, pair.value, pair.value_len))) {
350  eprintf("overflow on line %d: %s=\"%s\"\n",
351  line, pair.key, pair.value);
352  break;
353  }
354  }
355  }
356 
357  fclose(file);
358 out:
359  return status;
360 }
361 
362 static int config_init(
363  struct idmap_config *config)
364 {
365  int status;
366 #ifdef __REACTOS__
367  char config_path[MAX_PATH];
368 #endif
369 
370  /* load default values */
372  if (status) {
373  eprintf("config_defaults() failed with %d\n", status);
374  goto out;
375  }
376 
377 #ifdef __REACTOS__
378  if (GetSystemDirectoryA(config_path, ARRAYSIZE(config_path)))
379  {
380  StringCchCatA(config_path, ARRAYSIZE(config_path), "\\drivers\\etc\\ms-nfs41-idmap.conf");
381  }
382  else
383  {
384  StringCchCopyA(config_path, ARRAYSIZE(config_path), "C:\\ReactOS\\system32\\drivers\\etc\\ms-nfs41-idmap.conf");
385  }
386 #endif
387 
388  /* load configuration from file */
389 #ifdef __REACTOS__
390  status = config_load(config, config_path);
391 #else
393 #endif
394  if (status) {
395 #ifdef __REACTOS__
396  eprintf("config_load('%s') failed with %d\n", config_path, status);
397 #else
398  eprintf("config_load('%s') failed with %d\n", CONFIG_FILENAME, status);
399 #endif
400  goto out;
401  }
402 out:
403  return status;
404 }
405 
406 
407 /* generic cache */
408 typedef struct list_entry* (*entry_alloc_fn)();
409 typedef void (*entry_free_fn)(struct list_entry*);
410 typedef void (*entry_copy_fn)(struct list_entry*, const struct list_entry*);
411 
412 struct cache_ops {
416 };
417 
418 struct idmap_cache {
419  struct list_entry head;
420  const struct cache_ops *ops;
421  SRWLOCK lock;
422 };
423 
424 
425 static void cache_init(
426  struct idmap_cache *cache,
427  const struct cache_ops *ops)
428 {
429  list_init(&cache->head);
430  cache->ops = ops;
432 }
433 
434 static void cache_cleanup(
435  struct idmap_cache *cache)
436 {
437  struct list_entry *entry, *tmp;
438  list_for_each_tmp(entry, tmp, &cache->head)
439  cache->ops->entry_free(entry);
440  list_init(&cache->head);
441 }
442 
443 static int cache_insert(
444  struct idmap_cache *cache,
445  const struct idmap_lookup *lookup,
446  const struct list_entry *src)
447 {
448  struct list_entry *entry;
449  int status = NO_ERROR;
450 
452 
453  /* search for an existing match */
454  entry = list_search(&cache->head, lookup->value, lookup->compare);
455  if (entry) {
456  /* overwrite the existing entry with the new results */
457  cache->ops->entry_copy(entry, src);
458  goto out;
459  }
460 
461  /* initialize a new entry and add it to the list */
462  entry = cache->ops->entry_alloc();
463  if (entry == NULL) {
464  status = GetLastError();
465  goto out;
466  }
467  cache->ops->entry_copy(entry, src);
468  list_add_head(&cache->head, entry);
469 out:
471  return status;
472 }
473 
474 static int cache_lookup(
475  struct idmap_cache *cache,
476  const struct idmap_lookup *lookup,
477  struct list_entry *entry_out)
478 {
479  struct list_entry *entry;
480  int status = ERROR_NOT_FOUND;
481 
483 
484  entry = list_search(&cache->head, lookup->value, lookup->compare);
485  if (entry) {
486  /* make a copy for use outside of the lock */
487  cache->ops->entry_copy(entry_out, entry);
488  status = NO_ERROR;
489  }
490 
492  return status;
493 }
494 
495 
496 /* user cache */
497 struct idmap_user {
504 };
505 
506 static struct list_entry* user_cache_alloc()
507 {
508  struct idmap_user *user = calloc(1, sizeof(struct idmap_user));
509  return user == NULL ? NULL : &user->entry;
510 }
511 static void user_cache_free(struct list_entry *entry)
512 {
514 }
515 static void user_cache_copy(
516  struct list_entry *lhs,
517  const struct list_entry *rhs)
518 {
519  struct idmap_user *dst = list_container(lhs, struct idmap_user, entry);
520  const struct idmap_user *src = list_container(rhs, const struct idmap_user, entry);
521  StringCchCopyA(dst->username, VAL_LEN, src->username);
522  StringCchCopyA(dst->principal, VAL_LEN, src->principal);
523  dst->uid = src->uid;
524  dst->gid = src->gid;
525  dst->last_updated = src->last_updated;
526 }
527 static const struct cache_ops user_cache_ops = {
531 };
532 
533 
534 /* group cache */
535 struct idmap_group {
537  char name[VAL_LEN];
540 };
541 
543 {
544  struct idmap_group *group = calloc(1, sizeof(struct idmap_group));
545  return group == NULL ? NULL : &group->entry;
546 }
547 static void group_cache_free(struct list_entry *entry)
548 {
550 }
551 static void group_cache_copy(
552  struct list_entry *lhs,
553  const struct list_entry *rhs)
554 {
555  struct idmap_group *dst = list_container(lhs, struct idmap_group, entry);
556  const struct idmap_group *src = list_container(rhs, const struct idmap_group, entry);
557  StringCchCopyA(dst->name, VAL_LEN, src->name);
558  dst->gid = src->gid;
559  dst->last_updated = src->last_updated;
560 }
561 static const struct cache_ops group_cache_ops = {
565 };
566 
567 
568 /* ldap context */
574 };
575 
576 
577 static int idmap_filter(
578  struct idmap_config *config,
579  const struct idmap_lookup *lookup,
580  char *filter,
581  size_t filter_len)
582 {
583  UINT_PTR i;
584  int status = NO_ERROR;
585 
586  switch (lookup->type) {
587  case TYPE_INT:
588  i = (UINT_PTR)lookup->value;
589  if (FAILED(StringCchPrintfA(filter, filter_len,
590  "(&(objectClass=%s)(%s=%u))",
591  config->classes[lookup->klass],
592  config->attributes[lookup->attr], (UINT)i))) {
594  eprintf("ldap filter buffer overflow: '%s=%u'\n",
595  config->attributes[lookup->attr], (UINT)i);
596  }
597  break;
598 
599  case TYPE_STR:
600  if (FAILED(StringCchPrintfA(filter, filter_len,
601  "(&(objectClass=%s)(%s=%s))",
602  config->classes[lookup->klass],
603  config->attributes[lookup->attr], lookup->value))) {
605  eprintf("ldap filter buffer overflow: '%s=%s'\n",
606  config->attributes[lookup->attr], lookup->value);
607  }
608  break;
609 
610  default:
612  break;
613  }
614  return status;
615 }
616 
617 static int idmap_query_attrs(
618  struct idmap_context *context,
619  const struct idmap_lookup *lookup,
620  const unsigned attributes,
621  const unsigned optional,
622  PCHAR *values[],
623  const int len)
624 {
625  char filter[FILTER_LEN];
626  struct idmap_config *config = &context->config;
627  LDAPMessage *res = NULL, *entry;
628  int i, status;
629 
630  /* format the ldap filter */
632  if (status)
633  goto out;
634 
635  /* send the ldap query */
636  status = ldap_search_st(context->ldap, config->base,
638  if (status) {
639  eprintf("ldap search for '%s' failed with %d: %s\n",
642  goto out;
643  }
644 
645  entry = ldap_first_entry(context->ldap, res);
646  if (entry == NULL) {
648  eprintf("ldap search for '%s' failed with %d: %s\n",
651  goto out;
652  }
653 
654  /* fetch the attributes */
655  for (i = 0; i < len; i++) {
656  if (ATTR_ISSET(attributes, i)) {
657  values[i] = ldap_get_values(context->ldap,
658  entry, config->attributes[i]);
659 
660  /* fail if required attributes are missing */
661  if (values[i] == NULL && !ATTR_ISSET(optional, i)) {
663  eprintf("ldap entry for '%s' missing required "
664  "attribute '%s', returning %d: %s\n",
665  filter, config->attributes[i],
668  goto out;
669  }
670  }
671  }
672 out:
673  if (res) ldap_msgfree(res);
674  return status;
675 }
676 
677 static int idmap_lookup_user(
678  struct idmap_context *context,
679  const struct idmap_lookup *lookup,
680  struct idmap_user *user)
681 {
683  const unsigned attributes = ATTR_FLAG(ATTR_USER_NAME)
686  | ATTR_FLAG(ATTR_GID);
687  /* principal is optional; we'll cache it if we have it */
688  const unsigned optional = ATTR_FLAG(ATTR_PRINCIPAL);
689  int i, status;
690 
691  /* check the user cache for an existing entry */
692  status = cache_lookup(&context->users, lookup, &user->entry);
693  if (status == NO_ERROR) {
694  /* don't return expired entries; query new attributes
695  * and overwrite the entry with cache_insert() */
696  if (time(NULL) - user->last_updated < context->config.cache_ttl)
697  goto out;
698  }
699 
700  /* send the query to the ldap server */
703  if (status)
704  goto out_free_values;
705 
706  /* parse attributes */
707  if (FAILED(StringCchCopyA(user->username, VAL_LEN,
708  *values[ATTR_USER_NAME]))) {
709  eprintf("ldap attribute %s='%s' longer than %u characters\n",
710  context->config.attributes[ATTR_USER_NAME],
713  goto out_free_values;
714  }
715  if (FAILED(StringCchCopyA(user->principal, VAL_LEN,
717  eprintf("ldap attribute %s='%s' longer than %u characters\n",
718  context->config.attributes[ATTR_PRINCIPAL],
721  goto out_free_values;
722  }
723  if (!parse_uint(*values[ATTR_UID], &user->uid)) {
724  eprintf("failed to parse ldap attribute %s='%s'\n",
725  context->config.attributes[ATTR_UID], *values[ATTR_UID]);
727  goto out_free_values;
728  }
729  if (!parse_uint(*values[ATTR_GID], &user->gid)) {
730  eprintf("failed to parse ldap attribute %s='%s'\n",
731  context->config.attributes[ATTR_GID], *values[ATTR_GID]);
733  goto out_free_values;
734  }
735  user->last_updated = time(NULL);
736 
737  if (context->config.cache_ttl) {
738  /* insert the entry into the cache */
739  cache_insert(&context->users, lookup, &user->entry);
740  }
741 out_free_values:
742  for (i = 0; i < NUM_ATTRIBUTES; i++)
744 out:
745  return status;
746 }
747 
749  struct idmap_context *context,
750  const struct idmap_lookup *lookup,
751  struct idmap_group *group)
752 {
754  const unsigned attributes = ATTR_FLAG(ATTR_GROUP_NAME)
755  | ATTR_FLAG(ATTR_GID);
756  int i, status;
757 
758  /* check the group cache for an existing entry */
759  status = cache_lookup(&context->groups, lookup, &group->entry);
760  if (status == NO_ERROR) {
761  /* don't return expired entries; query new attributes
762  * and overwrite the entry with cache_insert() */
763  if (time(NULL) - group->last_updated < context->config.cache_ttl)
764  goto out;
765  }
766 
767  /* send the query to the ldap server */
770  if (status)
771  goto out_free_values;
772 
773  /* parse attributes */
774  if (FAILED(StringCchCopyA(group->name, VAL_LEN,
775  *values[ATTR_GROUP_NAME]))) {
776  eprintf("ldap attribute %s='%s' longer than %u characters\n",
777  context->config.attributes[ATTR_GROUP_NAME],
780  goto out_free_values;
781  }
782  if (!parse_uint(*values[ATTR_GID], &group->gid)) {
783  eprintf("failed to parse ldap attribute %s='%s'\n",
784  context->config.attributes[ATTR_GID], *values[ATTR_GID]);
786  goto out_free_values;
787  }
788  group->last_updated = time(NULL);
789 
790  if (context->config.cache_ttl) {
791  /* insert the entry into the cache */
792  cache_insert(&context->groups, lookup, &group->entry);
793  }
794 out_free_values:
795  for (i = 0; i < NUM_ATTRIBUTES; i++)
797 out:
798  return status;
799 }
800 
801 
802 /* public idmap interface */
804  struct idmap_context **context_out)
805 {
806  struct idmap_context *context;
807  int status = NO_ERROR;
808 
809  context = calloc(1, sizeof(struct idmap_context));
810  if (context == NULL) {
811  status = GetLastError();
812  goto out;
813  }
814 
815  /* initialize the caches */
816  cache_init(&context->users, &user_cache_ops);
817  cache_init(&context->groups, &group_cache_ops);
818 
819  /* load ldap configuration from file */
820  status = config_init(&context->config);
821  if (status) {
822  eprintf("config_init() failed with %d\n", status);
823  goto out_err_free;
824  }
825 
826  /* initialize ldap and configure options */
827  context->ldap = ldap_init(context->config.hostname, context->config.port);
828  if (context->ldap == NULL) {
830  eprintf("ldap_init(%s) failed with %d: %s\n",
831  context->config.hostname, status, ldap_err2stringA(status));
833  goto out_err_free;
834  }
835 
837  (void *)&context->config.version);
838  if (status != LDAP_SUCCESS) {
839  eprintf("ldap_set_option(version=%d) failed with %d\n",
840  context->config.version, status);
842  goto out_err_free;
843  }
844 
845  if (context->config.timeout) {
847  (void *)&context->config.timeout);
848  if (status != LDAP_SUCCESS) {
849  eprintf("ldap_set_option(timeout=%d) failed with %d\n",
850  context->config.timeout, status);
852  goto out_err_free;
853  }
854  }
855 
856  *context_out = context;
857 out:
858  return status;
859 
860 out_err_free:
862  goto out;
863 }
864 
866  struct idmap_context *context)
867 {
868  /* clean up the connection */
869  if (context->ldap)
870  ldap_unbind(context->ldap);
871 
872  cache_cleanup(&context->users);
873  cache_cleanup(&context->groups);
874  free(context);
875 }
876 
877 
878 /* username -> uid, gid */
879 static int username_cmp(const struct list_entry *list, const void *value)
880 {
881  const struct idmap_user *entry = list_container(list,
882  const struct idmap_user, entry);
883  const char *username = (const char*)value;
884  return strcmp(entry->username, username);
885 }
886 
888  struct idmap_context *context,
889  const char *username,
890  uid_t *uid_out,
891  gid_t *gid_out)
892 {
895  struct idmap_user user;
896  int status;
897 
898  if (context == NULL)
899  return ERROR_FILE_NOT_FOUND;
900 
901  dprintf(IDLVL, "--> nfs41_idmap_name_to_ids('%s')\n", username);
902 
903  lookup.value = username;
904 
905  /* look up the user entry */
907  if (status) {
908  dprintf(IDLVL, "<-- nfs41_idmap_name_to_ids('%s') "
909  "failed with %d\n", username, status);
910  goto out;
911  }
912 
913  *uid_out = user.uid;
914  *gid_out = user.gid;
915  dprintf(IDLVL, "<-- nfs41_idmap_name_to_ids('%s') "
916  "returning uid=%u, gid=%u\n", username, user.uid, user.gid);
917 out:
918  return status;
919 }
920 
921 /* uid -> username */
922 static int uid_cmp(const struct list_entry *list, const void *value)
923 {
924  const struct idmap_user *entry = list_container(list,
925  const struct idmap_user, entry);
926  const UINT_PTR uid = (const UINT_PTR)value;
927  return (UINT)uid - entry->uid;
928 }
929 
931  struct idmap_context *context,
932  uid_t uid,
933  char *name,
934  size_t len)
935 {
936  UINT_PTR uidp = uid; /* convert to pointer size to pass as void* */
938  struct idmap_user user;
939  int status;
940 
941  dprintf(IDLVL, "--> nfs41_idmap_uid_to_name(%u)\n", uid);
942 
943  lookup.value = (const void*)uidp;
944 
945  /* look up the user entry */
947  if (status) {
948  dprintf(IDLVL, "<-- nfs41_idmap_uid_to_name(%u) "
949  "failed with %d\n", uid, status);
950  goto out;
951  }
952 
953  if (FAILED(StringCchCopyA(name, len, user.username))) {
955  eprintf("username buffer overflow: '%s' > %u\n",
956  user.username, len);
957  goto out;
958  }
959 
960  dprintf(IDLVL, "<-- nfs41_idmap_uid_to_name(%u) "
961  "returning '%s'\n", uid, name);
962 out:
963  return status;
964 }
965 
966 /* principal -> uid, gid */
967 static int principal_cmp(const struct list_entry *list, const void *value)
968 {
969  const struct idmap_user *entry = list_container(list,
970  const struct idmap_user, entry);
971  const char *principal = (const char*)value;
972  return strcmp(entry->principal, principal);
973 }
974 
976  struct idmap_context *context,
977  const char *principal,
978  uid_t *uid_out,
979  gid_t *gid_out)
980 {
983  struct idmap_user user;
984  int status;
985 
986  dprintf(IDLVL, "--> nfs41_idmap_principal_to_ids('%s')\n", principal);
987 
988  lookup.value = principal;
989 
990  /* look up the user entry */
992  if (status) {
993  dprintf(IDLVL, "<-- nfs41_idmap_principal_to_ids('%s') "
994  "failed with %d\n", principal, status);
995  goto out;
996  }
997 
998  *uid_out = user.uid;
999  *gid_out = user.gid;
1000  dprintf(IDLVL, "<-- nfs41_idmap_principal_to_ids('%s') "
1001  "returning uid=%u, gid=%u\n", principal, user.uid, user.gid);
1002 out:
1003  return status;
1004 }
1005 
1006 /* group -> gid */
1007 static int group_cmp(const struct list_entry *list, const void *value)
1008 {
1009  const struct idmap_group *entry = list_container(list,
1010  const struct idmap_group, entry);
1011  const char *group = (const char*)value;
1012  return strcmp(entry->name, group);
1013 }
1014 
1016  struct idmap_context *context,
1017  const char *name,
1018  gid_t *gid_out)
1019 {
1020  struct idmap_lookup lookup = { ATTR_GROUP_NAME,
1022  struct idmap_group group;
1023  int status;
1024 
1025  dprintf(IDLVL, "--> nfs41_idmap_group_to_gid('%s')\n", name);
1026 
1027  lookup.value = name;
1028 
1029  /* look up the group entry */
1031  if (status) {
1032  dprintf(IDLVL, "<-- nfs41_idmap_group_to_gid('%s') "
1033  "failed with %d\n", name, status);
1034  goto out;
1035  }
1036 
1037  *gid_out = group.gid;
1038  dprintf(IDLVL, "<-- nfs41_idmap_group_to_gid('%s') "
1039  "returning %u\n", name, group.gid);
1040 out:
1041  return status;
1042 }
1043 
1044 /* gid -> group */
1045 static int gid_cmp(const struct list_entry *list, const void *value)
1046 {
1047  const struct idmap_group *entry = list_container(list,
1048  const struct idmap_group, entry);
1049  const UINT_PTR gid = (const UINT_PTR)value;
1050  return (UINT)gid - entry->gid;
1051 }
1052 
1054  struct idmap_context *context,
1055  gid_t gid,
1056  char *name,
1057  size_t len)
1058 {
1059  UINT_PTR gidp = gid; /* convert to pointer size to pass as void* */
1061  struct idmap_group group;
1062  int status;
1063 
1064  dprintf(IDLVL, "--> nfs41_idmap_gid_to_group(%u)\n", gid);
1065 
1066  lookup.value = (const void*)gidp;
1067 
1068  /* look up the group entry */
1070  if (status) {
1071  dprintf(IDLVL, "<-- nfs41_idmap_gid_to_group(%u) "
1072  "failed with %d\n", gid, status);
1073  goto out;
1074  }
1075 
1076  if (FAILED(StringCchCopyA(name, len, group.name))) {
1078  eprintf("group name buffer overflow: '%s' > %u\n",
1079  group.name, len);
1080  goto out;
1081  }
1082 
1083  dprintf(IDLVL, "<-- nfs41_idmap_gid_to_group(%u) "
1084  "returning '%s'\n", gid, name);
1085 out:
1086  return status;
1087 }
time_t last_updated
Definition: idmap.c:503
signed char * PCHAR
Definition: retypes.h:7
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
Definition: cache.c:46
VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:54
unsigned __int3264 UINT_PTR
Definition: activex.cpp:275
char * name
Definition: wpp.c:36
struct list_entry head
Definition: idmap.c:419
#define isspace(c)
Definition: acclib.h:69
UINT32 strtoul(const char *String, char **Terminator, UINT32 Base)
Definition: utclib.c:696
#define TRUE
Definition: types.h:120
static const struct cache_ops group_cache_ops
Definition: idmap.c:561
static int config_find_option(const struct config_pair *pair, const struct config_option **option)
Definition: idmap.c:275
#define OPT_ATTR(key, def, index)
Definition: idmap.c:119
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
int nfs41_idmap_group_to_gid(struct idmap_context *context, const char *name, gid_t *gid_out)
Definition: idmap.c:1015
WINLDAPAPI ULONG ldap_msgfree(LDAPMessage *)
LDAP * ldap
Definition: idmap.c:573
static struct list_entry * user_cache_alloc()
Definition: idmap.c:506
Definition: http.c:6587
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
entry_copy_fn entry_copy
Definition: idmap.c:415
#define ERROR_BUFFER_OVERFLOW
Definition: winerror.h:185
uid_t uid
Definition: idmap.c:501
static int uid_cmp(const struct list_entry *list, const void *value)
Definition: idmap.c:922
GLuint GLuint GLsizei count
Definition: gl.h:1545
static int cache_lookup(struct idmap_cache *cache, const struct idmap_lookup *lookup, struct list_entry *entry_out)
Definition: idmap.c:474
#define free
Definition: debug_ros.c:5
Definition: idmap.c:53
#define ldap_get_values
Definition: winldap.h:670
static int idmap_filter(struct idmap_config *config, const struct idmap_lookup *lookup, char *filter, size_t filter_len)
Definition: idmap.c:577
#define ATTR_ISSET(mask, attr)
Definition: idmap.c:60
GLboolean GLenum GLenum GLvoid * values
Definition: glext.h:5666
__WINE_SERVER_LIST_INLINE void list_add_head(struct list *list, struct list *elem)
Definition: list.h:96
WINLDAPAPI PLDAPMessage ldap_first_entry(LDAP *, LDAPMessage *)
UINT WINAPI GetSystemDirectoryA(OUT LPSTR lpBuffer, IN UINT uSize)
Definition: path.c:2282
WINLDAPAPI ULONG ldap_unbind(LDAP *)
size_t value_len
Definition: idmap.c:150
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
static ULONG lookup[16]
Definition: vga.c:46
GLuint buffer
Definition: glext.h:5915
void eprintf(LPCSTR format,...)
Definition: daemon_debug.c:86
int nfs41_idmap_name_to_ids(struct idmap_context *context, const char *username, uid_t *uid_out, gid_t *gid_out)
Definition: idmap.c:887
gid_t gid
Definition: idmap.c:502
Definition: dhcpd.h:245
const char * key
Definition: idmap.c:105
PCHAR CDECL ldap_err2stringA(ULONG err)
Definition: error.c:71
int errno
__u16 time
Definition: mkdosfs.c:366
struct idmap_cache users
Definition: idmap.c:571
const char * filename
Definition: ioapi.h:135
#define NO_ERROR
Definition: dderror.h:5
size_t offset
Definition: idmap.c:108
long uid_t
Definition: various.h:8
int32_t INT
Definition: typedefs.h:56
static int idmap_lookup_user(struct idmap_context *context, const struct idmap_lookup *lookup, struct idmap_user *user)
Definition: idmap.c:677
static int principal_cmp(const struct list_entry *list, const void *value)
Definition: idmap.c:967
#define LDAP_OPT_PROTOCOL_VERSION
Definition: winldap.h:145
ldap_class
Definition: idmap.c:42
#define LDAP_OPT_TIMELIMIT
Definition: winldap.h:133
#define OPT_INT(key, def, field)
Definition: idmap.c:113
gid_t gid
Definition: idmap.c:538
size_t key_len
Definition: idmap.c:150
char * hostname
Definition: ftp.c:88
char hostname[NFS41_HOSTNAME_LEN+1]
Definition: idmap.c:84
int nfs41_idmap_principal_to_ids(struct idmap_context *context, const char *principal, uid_t *uid_out, gid_t *gid_out)
Definition: idmap.c:975
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
ULONG CDECL LdapMapErrorToWin32(ULONG err)
Definition: error.c:302
static int idmap_query_attrs(struct idmap_context *context, const struct idmap_lookup *lookup, const unsigned attributes, const unsigned optional, PCHAR *values[], const int len)
Definition: idmap.c:617
STRSAFEAPI StringCchCopyNA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszSrc, size_t cchToCopy)
Definition: strsafe.h:230
enum ldap_class klass
Definition: idmap.c:66
list_compare_fn compare
Definition: idmap.c:72
GLsizei GLuint * groups
Definition: glext.h:11113
static int username_cmp(const struct list_entry *list, const void *value)
Definition: idmap.c:879
#define ldap_value_free
Definition: winldap.h:689
UINT gid_t
Definition: types.h:89
unsigned int BOOL
Definition: ntddk_ex.h:94
STRSAFEAPI StringCchCatA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszSrc)
Definition: strsafe.h:320
#define NFS41_HOSTNAME_LEN
Definition: nfs41_const.h:48
#define dprintf
Definition: regdump.c:33
#define ldap_search_st
Definition: winldap.h:680
time_t last_updated
Definition: idmap.c:539
static void user_cache_free(struct list_entry *entry)
Definition: idmap.c:511
STRSAFEAPI StringCchPrintfA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszFormat,...)
Definition: strsafe.h:520
enum ldap_attr attr
Definition: idmap.c:65
UINT timeout
Definition: idmap.c:87
const WCHAR * str
smooth NULL
Definition: ftsmooth.c:416
static const WCHAR version[]
Definition: asmname.c:64
HANDLE lock
Definition: cache.c:50
Definition: getopt.h:108
static int group_cmp(const struct list_entry *list, const void *value)
Definition: idmap.c:1007
Definition: parser.c:48
static void cache_cleanup(struct idmap_cache *cache)
Definition: idmap.c:434
entry_alloc_fn entry_alloc
Definition: idmap.c:413
enum config_type type
Definition: idmap.c:70
static void group_cache_free(struct list_entry *entry)
Definition: idmap.c:547
#define list_container(entry, type, field)
Definition: list.h:33
int nfs41_idmap_uid_to_name(struct idmap_context *context, uid_t uid, char *name, size_t len)
Definition: idmap.c:930
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
ldap_attr
Definition: idmap.c:49
Definition: msg.h:41
static BOOL parse_uint(const char *str, UINT *id_out)
Definition: idmap.c:223
GLuint GLenum option
Definition: glext.h:11211
_Check_return_ _CRTIMP int __cdecl stricmp(_In_z_ const char *_Str1, _In_z_ const char *_Str2)
#define LDAP_NO_RESULTS_RETURNED
Definition: winldap.h:114
static WCHAR username[]
Definition: url.c:32
char attributes[NUM_ATTRIBUTES][NAME_LEN]
Definition: idmap.c:91
#define IDLVL
Definition: idmap.c:35
static void group_cache_copy(struct list_entry *lhs, const struct list_entry *rhs)
Definition: idmap.c:551
char classes[NUM_CLASSES][NAME_LEN]
Definition: idmap.c:90
GLboolean GLuint group
Definition: glext.h:11120
const char * value
Definition: idmap.c:149
static const struct cache_ops user_cache_ops
Definition: idmap.c:527
char username[VAL_LEN]
Definition: idmap.c:499
struct list_entry entry
Definition: idmap.c:498
enum config_type type
Definition: idmap.c:107
if(!(yy_init))
Definition: macro.lex.yy.c:714
static int config_defaults(struct idmap_config *config)
Definition: idmap.c:243
const char * def
Definition: idmap.c:106
#define MAX_PATH
Definition: compat.h:26
const char file[]
Definition: icontest.c:11
static int idmap_lookup_group(struct idmap_context *context, const struct idmap_lookup *lookup, struct idmap_group *group)
Definition: idmap.c:748
const char * key
Definition: idmap.c:149
static FILE * out
Definition: regtests2xml.c:44
struct list_entry *(* entry_alloc_fn)()
Definition: idmap.c:408
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
config_type
Definition: idmap.c:99
#define ERANGE
Definition: acclib.h:92
#define ATTR_FLAG(attr)
Definition: idmap.c:59
const struct cache_ops * ops
Definition: idmap.c:420
char line[200]
Definition: main.c:97
entry_free_fn entry_free
Definition: idmap.c:414
int(* list_compare_fn)(const struct list_entry *, const void *)
Definition: list.h:100
#define LDAP_NO_SUCH_ATTRIBUTE
Definition: winldap.h:74
VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:82
uint32_t entry
Definition: isohybrid.c:63
SRWLOCK lock
Definition: idmap.c:421
GLenum GLsizei len
Definition: glext.h:6722
Definition: _list.h:228
struct list_entry entry
Definition: idmap.c:536
char principal[VAL_LEN]
Definition: idmap.c:500
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
_Check_return_ _CRTIMP FILE *__cdecl fopen(_In_z_ const char *_Filename, _In_z_ const char *_Mode)
GLenum src
Definition: glext.h:6340
#define VAL_LEN
Definition: idmap.c:39
VOID WINAPI InitializeSRWLock(PSRWLOCK Lock)
Definition: sync.c:75
#define FILTER_LEN
Definition: idmap.c:37
#define ldap_init
Definition: winldap.h:638
void(* entry_copy_fn)(struct list_entry *, const struct list_entry *)
Definition: idmap.c:410
static int gid_cmp(const struct list_entry *list, const void *value)
Definition: idmap.c:1045
#define LDAP_SCOPE_SUBTREE
Definition: winldap.h:190
#define OPT_STR(key, def, field, len)
Definition: idmap.c:115
static struct list_entry * list_search(const struct list_entry *head, const void *value, list_compare_fn compare)
Definition: list.h:102
static int cache_insert(struct idmap_cache *cache, const struct idmap_lookup *lookup, const struct list_entry *src)
Definition: idmap.c:443
STRSAFEAPI StringCchCopyA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszSrc)
Definition: strsafe.h:145
size_t max_len
Definition: idmap.c:109
_Check_return_opt_ _CRTIMP char *__cdecl fgets(_Out_writes_z_(_MaxCount) char *_Buf, _In_ int _MaxCount, _Inout_ FILE *_File)
ULONG CDECL LdapGetLastError(void)
Definition: error.c:184
static int config_load(struct idmap_config *config, const char *filename)
Definition: idmap.c:293
__kernel_time_t time_t
Definition: linux.h:252
INT cache_ttl
Definition: idmap.c:95
GLenum GLenum dst
Definition: glext.h:6340
Definition: _pair.h:47
Definition: list.h:27
unsigned int UINT
Definition: ndis.h:50
__kernel_ptrdiff_t ptrdiff_t
Definition: linux.h:247
#define ERROR_NOT_FOUND
Definition: winerror.h:690
static const char CONFIG_FILENAME[]
Definition: idmap.c:79
UINT32 uint32_t
Definition: types.h:75
char * strchr(const char *String, int ch)
Definition: utclib.c:501
static const struct config_option g_options[]
Definition: idmap.c:123
#define LDAP_SUCCESS
Definition: winldap.h:59
int nfs41_idmap_gid_to_group(struct idmap_context *context, gid_t gid, char *name, size_t len)
Definition: idmap.c:1053
static void user_cache_copy(struct list_entry *lhs, const struct list_entry *rhs)
Definition: idmap.c:515
static int config_init(struct idmap_config *config)
Definition: idmap.c:362
Definition: name.c:36
#define list_for_each_tmp(entry, tmp, head)
Definition: list.h:39
#define calloc
Definition: rosglue.h:14
GLuint res
Definition: glext.h:9613
Definition: idmap.c:54
__WINE_SERVER_LIST_INLINE void list_init(struct list *list)
Definition: list.h:149
GLenum GLuint id
Definition: glext.h:5579
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
UINT version
Definition: idmap.c:86
static struct list_entry * group_cache_alloc()
Definition: idmap.c:542
int nfs41_idmap_create(struct idmap_context **context_out)
Definition: idmap.c:803
#define OPT_CLASS(key, def, index)
Definition: idmap.c:117
const void * value
Definition: idmap.c:73
USHORT port
Definition: uri.c:227
#define ldap_set_option
Definition: winldap.h:641
static void cache_init(struct idmap_cache *cache, const struct cache_ops *ops)
Definition: idmap.c:425
static SERVICE_STATUS status
Definition: service.c:31
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glext.h:7005
void user(int argc, const char *argv[])
Definition: cmds.c:1350
UINT port
Definition: idmap.c:85
void nfs41_idmap_free(struct idmap_context *context)
Definition: idmap.c:865
VOID WINAPI AcquireSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:61
VOID WINAPI ReleaseSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:89
void(* entry_free_fn)(struct list_entry *)
Definition: idmap.c:409
#define ULONG_MAX
Definition: limits.h:44
WCHAR * name
Definition: name.c:40
static int config_parse_pair(char *line, struct config_pair *pair)
Definition: idmap.c:153
#define NAME_LEN
Definition: idmap.c:38
Definition: fci.c:126
Definition: ps.c:97
GLuint const GLchar * name
Definition: glext.h:6031