ReactOS  0.4.15-dev-489-g75a0787
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  status = GetLastError();
385  eprintf("GetSystemDirectoryA failed with %ld\n", GetLastError());
386  goto out;
387  }
388 #endif
389 
390  /* load configuration from file */
391 #ifdef __REACTOS__
392  status = config_load(config, config_path);
393 #else
395 #endif
396  if (status) {
397 #ifdef __REACTOS__
398  eprintf("config_load('%s') failed with %d\n", config_path, status);
399 #else
400  eprintf("config_load('%s') failed with %d\n", CONFIG_FILENAME, status);
401 #endif
402  goto out;
403  }
404 out:
405  return status;
406 }
407 
408 
409 /* generic cache */
410 typedef struct list_entry* (*entry_alloc_fn)();
411 typedef void (*entry_free_fn)(struct list_entry*);
412 typedef void (*entry_copy_fn)(struct list_entry*, const struct list_entry*);
413 
414 struct cache_ops {
418 };
419 
420 struct idmap_cache {
421  struct list_entry head;
422  const struct cache_ops *ops;
423  SRWLOCK lock;
424 };
425 
426 
427 static void cache_init(
428  struct idmap_cache *cache,
429  const struct cache_ops *ops)
430 {
431  list_init(&cache->head);
432  cache->ops = ops;
434 }
435 
436 static void cache_cleanup(
437  struct idmap_cache *cache)
438 {
439  struct list_entry *entry, *tmp;
440  list_for_each_tmp(entry, tmp, &cache->head)
441  cache->ops->entry_free(entry);
442  list_init(&cache->head);
443 }
444 
445 static int cache_insert(
446  struct idmap_cache *cache,
447  const struct idmap_lookup *lookup,
448  const struct list_entry *src)
449 {
450  struct list_entry *entry;
451  int status = NO_ERROR;
452 
454 
455  /* search for an existing match */
456  entry = list_search(&cache->head, lookup->value, lookup->compare);
457  if (entry) {
458  /* overwrite the existing entry with the new results */
459  cache->ops->entry_copy(entry, src);
460  goto out;
461  }
462 
463  /* initialize a new entry and add it to the list */
464  entry = cache->ops->entry_alloc();
465  if (entry == NULL) {
466  status = GetLastError();
467  goto out;
468  }
469  cache->ops->entry_copy(entry, src);
470  list_add_head(&cache->head, entry);
471 out:
473  return status;
474 }
475 
476 static int cache_lookup(
477  struct idmap_cache *cache,
478  const struct idmap_lookup *lookup,
479  struct list_entry *entry_out)
480 {
481  struct list_entry *entry;
482  int status = ERROR_NOT_FOUND;
483 
485 
486  entry = list_search(&cache->head, lookup->value, lookup->compare);
487  if (entry) {
488  /* make a copy for use outside of the lock */
489  cache->ops->entry_copy(entry_out, entry);
490  status = NO_ERROR;
491  }
492 
494  return status;
495 }
496 
497 
498 /* user cache */
499 struct idmap_user {
506 };
507 
508 static struct list_entry* user_cache_alloc()
509 {
510  struct idmap_user *user = calloc(1, sizeof(struct idmap_user));
511  return user == NULL ? NULL : &user->entry;
512 }
513 static void user_cache_free(struct list_entry *entry)
514 {
516 }
517 static void user_cache_copy(
518  struct list_entry *lhs,
519  const struct list_entry *rhs)
520 {
521  struct idmap_user *dst = list_container(lhs, struct idmap_user, entry);
522  const struct idmap_user *src = list_container(rhs, const struct idmap_user, entry);
523  StringCchCopyA(dst->username, VAL_LEN, src->username);
524  StringCchCopyA(dst->principal, VAL_LEN, src->principal);
525  dst->uid = src->uid;
526  dst->gid = src->gid;
527  dst->last_updated = src->last_updated;
528 }
529 static const struct cache_ops user_cache_ops = {
533 };
534 
535 
536 /* group cache */
537 struct idmap_group {
539  char name[VAL_LEN];
542 };
543 
545 {
546  struct idmap_group *group = calloc(1, sizeof(struct idmap_group));
547  return group == NULL ? NULL : &group->entry;
548 }
549 static void group_cache_free(struct list_entry *entry)
550 {
552 }
553 static void group_cache_copy(
554  struct list_entry *lhs,
555  const struct list_entry *rhs)
556 {
557  struct idmap_group *dst = list_container(lhs, struct idmap_group, entry);
558  const struct idmap_group *src = list_container(rhs, const struct idmap_group, entry);
559  StringCchCopyA(dst->name, VAL_LEN, src->name);
560  dst->gid = src->gid;
561  dst->last_updated = src->last_updated;
562 }
563 static const struct cache_ops group_cache_ops = {
567 };
568 
569 
570 /* ldap context */
576 };
577 
578 
579 static int idmap_filter(
580  struct idmap_config *config,
581  const struct idmap_lookup *lookup,
582  char *filter,
583  size_t filter_len)
584 {
585  UINT_PTR i;
586  int status = NO_ERROR;
587 
588  switch (lookup->type) {
589  case TYPE_INT:
590  i = (UINT_PTR)lookup->value;
591  if (FAILED(StringCchPrintfA(filter, filter_len,
592  "(&(objectClass=%s)(%s=%u))",
593  config->classes[lookup->klass],
594  config->attributes[lookup->attr], (UINT)i))) {
596  eprintf("ldap filter buffer overflow: '%s=%u'\n",
597  config->attributes[lookup->attr], (UINT)i);
598  }
599  break;
600 
601  case TYPE_STR:
602  if (FAILED(StringCchPrintfA(filter, filter_len,
603  "(&(objectClass=%s)(%s=%s))",
604  config->classes[lookup->klass],
605  config->attributes[lookup->attr], lookup->value))) {
607  eprintf("ldap filter buffer overflow: '%s=%s'\n",
608  config->attributes[lookup->attr], lookup->value);
609  }
610  break;
611 
612  default:
614  break;
615  }
616  return status;
617 }
618 
619 static int idmap_query_attrs(
620  struct idmap_context *context,
621  const struct idmap_lookup *lookup,
622  const unsigned attributes,
623  const unsigned optional,
624  PCHAR *values[],
625  const int len)
626 {
627  char filter[FILTER_LEN];
628  struct idmap_config *config = &context->config;
629  LDAPMessage *res = NULL, *entry;
630  int i, status;
631 
632  /* format the ldap filter */
634  if (status)
635  goto out;
636 
637  /* send the ldap query */
638  status = ldap_search_st(context->ldap, config->base,
640  if (status) {
641  eprintf("ldap search for '%s' failed with %d: %s\n",
644  goto out;
645  }
646 
647  entry = ldap_first_entry(context->ldap, res);
648  if (entry == NULL) {
650  eprintf("ldap search for '%s' failed with %d: %s\n",
653  goto out;
654  }
655 
656  /* fetch the attributes */
657  for (i = 0; i < len; i++) {
658  if (ATTR_ISSET(attributes, i)) {
659  values[i] = ldap_get_values(context->ldap,
660  entry, config->attributes[i]);
661 
662  /* fail if required attributes are missing */
663  if (values[i] == NULL && !ATTR_ISSET(optional, i)) {
665  eprintf("ldap entry for '%s' missing required "
666  "attribute '%s', returning %d: %s\n",
667  filter, config->attributes[i],
670  goto out;
671  }
672  }
673  }
674 out:
675  if (res) ldap_msgfree(res);
676  return status;
677 }
678 
679 static int idmap_lookup_user(
680  struct idmap_context *context,
681  const struct idmap_lookup *lookup,
682  struct idmap_user *user)
683 {
685  const unsigned attributes = ATTR_FLAG(ATTR_USER_NAME)
688  | ATTR_FLAG(ATTR_GID);
689  /* principal is optional; we'll cache it if we have it */
690  const unsigned optional = ATTR_FLAG(ATTR_PRINCIPAL);
691  int i, status;
692 
693  /* check the user cache for an existing entry */
694  status = cache_lookup(&context->users, lookup, &user->entry);
695  if (status == NO_ERROR) {
696  /* don't return expired entries; query new attributes
697  * and overwrite the entry with cache_insert() */
698  if (time(NULL) - user->last_updated < context->config.cache_ttl)
699  goto out;
700  }
701 
702  /* send the query to the ldap server */
705  if (status)
706  goto out_free_values;
707 
708  /* parse attributes */
709  if (FAILED(StringCchCopyA(user->username, VAL_LEN,
710  *values[ATTR_USER_NAME]))) {
711  eprintf("ldap attribute %s='%s' longer than %u characters\n",
712  context->config.attributes[ATTR_USER_NAME],
715  goto out_free_values;
716  }
717  if (FAILED(StringCchCopyA(user->principal, VAL_LEN,
719  eprintf("ldap attribute %s='%s' longer than %u characters\n",
720  context->config.attributes[ATTR_PRINCIPAL],
723  goto out_free_values;
724  }
725  if (!parse_uint(*values[ATTR_UID], &user->uid)) {
726  eprintf("failed to parse ldap attribute %s='%s'\n",
727  context->config.attributes[ATTR_UID], *values[ATTR_UID]);
729  goto out_free_values;
730  }
731  if (!parse_uint(*values[ATTR_GID], &user->gid)) {
732  eprintf("failed to parse ldap attribute %s='%s'\n",
733  context->config.attributes[ATTR_GID], *values[ATTR_GID]);
735  goto out_free_values;
736  }
737  user->last_updated = time(NULL);
738 
739  if (context->config.cache_ttl) {
740  /* insert the entry into the cache */
741  cache_insert(&context->users, lookup, &user->entry);
742  }
743 out_free_values:
744  for (i = 0; i < NUM_ATTRIBUTES; i++)
746 out:
747  return status;
748 }
749 
751  struct idmap_context *context,
752  const struct idmap_lookup *lookup,
753  struct idmap_group *group)
754 {
756  const unsigned attributes = ATTR_FLAG(ATTR_GROUP_NAME)
757  | ATTR_FLAG(ATTR_GID);
758  int i, status;
759 
760  /* check the group cache for an existing entry */
761  status = cache_lookup(&context->groups, lookup, &group->entry);
762  if (status == NO_ERROR) {
763  /* don't return expired entries; query new attributes
764  * and overwrite the entry with cache_insert() */
765  if (time(NULL) - group->last_updated < context->config.cache_ttl)
766  goto out;
767  }
768 
769  /* send the query to the ldap server */
772  if (status)
773  goto out_free_values;
774 
775  /* parse attributes */
776  if (FAILED(StringCchCopyA(group->name, VAL_LEN,
777  *values[ATTR_GROUP_NAME]))) {
778  eprintf("ldap attribute %s='%s' longer than %u characters\n",
779  context->config.attributes[ATTR_GROUP_NAME],
782  goto out_free_values;
783  }
784  if (!parse_uint(*values[ATTR_GID], &group->gid)) {
785  eprintf("failed to parse ldap attribute %s='%s'\n",
786  context->config.attributes[ATTR_GID], *values[ATTR_GID]);
788  goto out_free_values;
789  }
790  group->last_updated = time(NULL);
791 
792  if (context->config.cache_ttl) {
793  /* insert the entry into the cache */
794  cache_insert(&context->groups, lookup, &group->entry);
795  }
796 out_free_values:
797  for (i = 0; i < NUM_ATTRIBUTES; i++)
799 out:
800  return status;
801 }
802 
803 
804 /* public idmap interface */
806  struct idmap_context **context_out)
807 {
808  struct idmap_context *context;
809  int status = NO_ERROR;
810 
811  context = calloc(1, sizeof(struct idmap_context));
812  if (context == NULL) {
813  status = GetLastError();
814  goto out;
815  }
816 
817  /* initialize the caches */
818  cache_init(&context->users, &user_cache_ops);
819  cache_init(&context->groups, &group_cache_ops);
820 
821  /* load ldap configuration from file */
822  status = config_init(&context->config);
823  if (status) {
824  eprintf("config_init() failed with %d\n", status);
825  goto out_err_free;
826  }
827 
828  /* initialize ldap and configure options */
829  context->ldap = ldap_init(context->config.hostname, context->config.port);
830  if (context->ldap == NULL) {
832  eprintf("ldap_init(%s) failed with %d: %s\n",
833  context->config.hostname, status, ldap_err2stringA(status));
835  goto out_err_free;
836  }
837 
839  (void *)&context->config.version);
840  if (status != LDAP_SUCCESS) {
841  eprintf("ldap_set_option(version=%d) failed with %d\n",
842  context->config.version, status);
844  goto out_err_free;
845  }
846 
847  if (context->config.timeout) {
849  (void *)&context->config.timeout);
850  if (status != LDAP_SUCCESS) {
851  eprintf("ldap_set_option(timeout=%d) failed with %d\n",
852  context->config.timeout, status);
854  goto out_err_free;
855  }
856  }
857 
858  *context_out = context;
859 out:
860  return status;
861 
862 out_err_free:
864  goto out;
865 }
866 
868  struct idmap_context *context)
869 {
870  /* clean up the connection */
871  if (context->ldap)
872  ldap_unbind(context->ldap);
873 
874  cache_cleanup(&context->users);
875  cache_cleanup(&context->groups);
876  free(context);
877 }
878 
879 
880 /* username -> uid, gid */
881 static int username_cmp(const struct list_entry *list, const void *value)
882 {
883  const struct idmap_user *entry = list_container(list,
884  const struct idmap_user, entry);
885  const char *username = (const char*)value;
886  return strcmp(entry->username, username);
887 }
888 
890  struct idmap_context *context,
891  const char *username,
892  uid_t *uid_out,
893  gid_t *gid_out)
894 {
897  struct idmap_user user;
898  int status;
899 
900  if (context == NULL)
901  return ERROR_FILE_NOT_FOUND;
902 
903  dprintf(IDLVL, "--> nfs41_idmap_name_to_ids('%s')\n", username);
904 
905  lookup.value = username;
906 
907  /* look up the user entry */
909  if (status) {
910  dprintf(IDLVL, "<-- nfs41_idmap_name_to_ids('%s') "
911  "failed with %d\n", username, status);
912  goto out;
913  }
914 
915  *uid_out = user.uid;
916  *gid_out = user.gid;
917  dprintf(IDLVL, "<-- nfs41_idmap_name_to_ids('%s') "
918  "returning uid=%u, gid=%u\n", username, user.uid, user.gid);
919 out:
920  return status;
921 }
922 
923 /* uid -> username */
924 static int uid_cmp(const struct list_entry *list, const void *value)
925 {
926  const struct idmap_user *entry = list_container(list,
927  const struct idmap_user, entry);
928  const UINT_PTR uid = (const UINT_PTR)value;
929  return (UINT)uid - entry->uid;
930 }
931 
933  struct idmap_context *context,
934  uid_t uid,
935  char *name,
936  size_t len)
937 {
938  UINT_PTR uidp = uid; /* convert to pointer size to pass as void* */
940  struct idmap_user user;
941  int status;
942 
943  dprintf(IDLVL, "--> nfs41_idmap_uid_to_name(%u)\n", uid);
944 
945  lookup.value = (const void*)uidp;
946 
947  /* look up the user entry */
949  if (status) {
950  dprintf(IDLVL, "<-- nfs41_idmap_uid_to_name(%u) "
951  "failed with %d\n", uid, status);
952  goto out;
953  }
954 
955  if (FAILED(StringCchCopyA(name, len, user.username))) {
957  eprintf("username buffer overflow: '%s' > %u\n",
958  user.username, len);
959  goto out;
960  }
961 
962  dprintf(IDLVL, "<-- nfs41_idmap_uid_to_name(%u) "
963  "returning '%s'\n", uid, name);
964 out:
965  return status;
966 }
967 
968 /* principal -> uid, gid */
969 static int principal_cmp(const struct list_entry *list, const void *value)
970 {
971  const struct idmap_user *entry = list_container(list,
972  const struct idmap_user, entry);
973  const char *principal = (const char*)value;
974  return strcmp(entry->principal, principal);
975 }
976 
978  struct idmap_context *context,
979  const char *principal,
980  uid_t *uid_out,
981  gid_t *gid_out)
982 {
985  struct idmap_user user;
986  int status;
987 
988  dprintf(IDLVL, "--> nfs41_idmap_principal_to_ids('%s')\n", principal);
989 
990  lookup.value = principal;
991 
992  /* look up the user entry */
994  if (status) {
995  dprintf(IDLVL, "<-- nfs41_idmap_principal_to_ids('%s') "
996  "failed with %d\n", principal, status);
997  goto out;
998  }
999 
1000  *uid_out = user.uid;
1001  *gid_out = user.gid;
1002  dprintf(IDLVL, "<-- nfs41_idmap_principal_to_ids('%s') "
1003  "returning uid=%u, gid=%u\n", principal, user.uid, user.gid);
1004 out:
1005  return status;
1006 }
1007 
1008 /* group -> gid */
1009 static int group_cmp(const struct list_entry *list, const void *value)
1010 {
1011  const struct idmap_group *entry = list_container(list,
1012  const struct idmap_group, entry);
1013  const char *group = (const char*)value;
1014  return strcmp(entry->name, group);
1015 }
1016 
1018  struct idmap_context *context,
1019  const char *name,
1020  gid_t *gid_out)
1021 {
1022  struct idmap_lookup lookup = { ATTR_GROUP_NAME,
1024  struct idmap_group group;
1025  int status;
1026 
1027  dprintf(IDLVL, "--> nfs41_idmap_group_to_gid('%s')\n", name);
1028 
1029  lookup.value = name;
1030 
1031  /* look up the group entry */
1033  if (status) {
1034  dprintf(IDLVL, "<-- nfs41_idmap_group_to_gid('%s') "
1035  "failed with %d\n", name, status);
1036  goto out;
1037  }
1038 
1039  *gid_out = group.gid;
1040  dprintf(IDLVL, "<-- nfs41_idmap_group_to_gid('%s') "
1041  "returning %u\n", name, group.gid);
1042 out:
1043  return status;
1044 }
1045 
1046 /* gid -> group */
1047 static int gid_cmp(const struct list_entry *list, const void *value)
1048 {
1049  const struct idmap_group *entry = list_container(list,
1050  const struct idmap_group, entry);
1051  const UINT_PTR gid = (const UINT_PTR)value;
1052  return (UINT)gid - entry->gid;
1053 }
1054 
1056  struct idmap_context *context,
1057  gid_t gid,
1058  char *name,
1059  size_t len)
1060 {
1061  UINT_PTR gidp = gid; /* convert to pointer size to pass as void* */
1063  struct idmap_group group;
1064  int status;
1065 
1066  dprintf(IDLVL, "--> nfs41_idmap_gid_to_group(%u)\n", gid);
1067 
1068  lookup.value = (const void*)gidp;
1069 
1070  /* look up the group entry */
1072  if (status) {
1073  dprintf(IDLVL, "<-- nfs41_idmap_gid_to_group(%u) "
1074  "failed with %d\n", gid, status);
1075  goto out;
1076  }
1077 
1078  if (FAILED(StringCchCopyA(name, len, group.name))) {
1080  eprintf("group name buffer overflow: '%s' > %u\n",
1081  group.name, len);
1082  goto out;
1083  }
1084 
1085  dprintf(IDLVL, "<-- nfs41_idmap_gid_to_group(%u) "
1086  "returning '%s'\n", gid, name);
1087 out:
1088  return status;
1089 }
time_t last_updated
Definition: idmap.c:505
signed char * PCHAR
Definition: retypes.h:7
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
Definition: cache.c:48
VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:54
unsigned __int3264 UINT_PTR
Definition: activex.cpp:275
struct list_entry head
Definition: idmap.c:421
#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:563
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:1017
WINLDAPAPI ULONG ldap_msgfree(LDAPMessage *)
LDAP * ldap
Definition: idmap.c:575
static struct list_entry * user_cache_alloc()
Definition: idmap.c:508
Definition: http.c:7094
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
entry_copy_fn entry_copy
Definition: idmap.c:417
#define ERROR_BUFFER_OVERFLOW
Definition: winerror.h:185
uid_t uid
Definition: idmap.c:503
static int uid_cmp(const struct list_entry *list, const void *value)
Definition: idmap.c:924
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:476
#define free
Definition: debug_ros.c:5
Definition: idmap.c:53
static ULONG lookup[16]
Definition: vga.c:38
#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:579
#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
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:889
gid_t gid
Definition: idmap.c:504
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:573
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:57
static int idmap_lookup_user(struct idmap_context *context, const struct idmap_lookup *lookup, struct idmap_user *user)
Definition: idmap.c:679
static int principal_cmp(const struct list_entry *list, const void *value)
Definition: idmap.c:969
#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:540
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:977
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:619
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:881
#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:541
static void user_cache_free(struct list_entry *entry)
Definition: idmap.c:513
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:66
HANDLE lock
Definition: cache.c:52
Definition: getopt.h:108
static int group_cmp(const struct list_entry *list, const void *value)
Definition: idmap.c:1009
Definition: parser.c:48
static void cache_cleanup(struct idmap_cache *cache)
Definition: idmap.c:436
entry_alloc_fn entry_alloc
Definition: idmap.c:415
enum config_type type
Definition: idmap.c:70
static void group_cache_free(struct list_entry *entry)
Definition: idmap.c:549
#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:932
#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:553
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:529
char username[VAL_LEN]
Definition: idmap.c:501
struct list_entry entry
Definition: idmap.c:500
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:750
const char * key
Definition: idmap.c:149
static FILE * out
Definition: regtests2xml.c:44
char * name
Definition: compiler.c:66
struct list_entry *(* entry_alloc_fn)()
Definition: idmap.c:410
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:422
char line[200]
Definition: main.c:97
entry_free_fn entry_free
Definition: idmap.c:416
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:423
GLenum GLsizei len
Definition: glext.h:6722
Definition: _list.h:228
struct list_entry entry
Definition: idmap.c:538
char principal[VAL_LEN]
Definition: idmap.c:502
_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:412
static int gid_cmp(const struct list_entry *list, const void *value)
Definition: idmap.c:1047
#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:445
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:1055
static void user_cache_copy(struct list_entry *lhs, const struct list_entry *rhs)
Definition: idmap.c:517
static int config_init(struct idmap_config *config)
Definition: idmap.c:362
Definition: name.c:38
#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:544
int nfs41_idmap_create(struct idmap_context **context_out)
Definition: idmap.c:805
#define OPT_CLASS(key, def, index)
Definition: idmap.c:117
const void * value
Definition: idmap.c:73
USHORT port
Definition: uri.c:228
#define ldap_set_option
Definition: winldap.h:641
static void cache_init(struct idmap_cache *cache, const struct cache_ops *ops)
Definition: idmap.c:427
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:867
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:411
#define ULONG_MAX
Definition: limits.h:44
WCHAR * name
Definition: name.c:42
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