]> andersk Git - moira.git/blob - incremental/winad/winad.c
Deal better with null pointers. Corrects a seg fault we're seeing
[moira.git] / incremental / winad / winad.c
1 /* $Header$
2 /* test parameters for creating a user account - done 
3  * users 10 10 a_chen 31275 sh cmd Lastname Firstname Middlename 0 950000000 STAFF a_chen 31275 sh cmd Lastname Firstname Middlename 2 950000000 STAFF
4  * users 10 10 a_chen 31275 sh cmd Lastname Firstname Middlename 2 950000000 STAFF a_chen 31275 sh cmd Lastname Firstname Middlename 1 950000000 STAFF
5  *   login, unix_uid, shell, winconsoleshell, last, first, middle, status, clearid, type
6  *
7  * test parameters for deactivating/deleting a user account - done
8  * users 10 10 testacc 31275 sh cmd Lastname Firstname Middlename 1 950000000 STAFF testacc 31275 sh cmd Lastname Firstname Middlename 3 950000000 STAFF 
9  * users 10 10 testacc 31275 sh cmd Lastname Firstname Middlename 2 950000000 STAFF testacc 31275 sh cmd Lastname Firstname Middlename 3 950000000 STAFF 
10  *   login, unix_uid, shell, winconsoleshell, last, first, middle, status, clearid, type
11  * comment: clearid is the MIT ID
12  *
13  * test parameters for reactivating a user account - done
14  * users 10 10 testacc 31275 sh cmd Lastname Firstname Middlename 3 950000000 STAFF testacc 31275 sh cmd Lastname Firstname Middlename 2 950000000 STAFF 
15  *   login, unix_uid, shell, winconsoleshell, last, first, middle, status, clearid, type
16  *
17  * test parameters for updating user account info - done
18  * users 10 10 testacc 31275 sh cmd Lastname Firstname Middlename 2 950000000 STAFF testacc 31275 sh cmd newLastname Firstname Middlename 2 950000000 STAFF 
19  * users 10 10 6_d0006 950 sh cmd Lastname Firstname Middlename 1 900012345 STAFF 6_d0006 950 sh cmd Lastname Firstname Middlename 1 950012345 STAFF
20  *   login, unix_uid, shell, winconsoleshell, last, first, middle, status, clearid, type
21  *   currently, if the unix_id doesn't change, only the U_UID or U_MITID fields will be updated
22  *
23  * test parameters for changing user name - testing
24  * users 10 10 testacc 31275 sh cmd Lastname Firstname Middlename 2 950000000 STAFF testacc1 31275 sh cmd Lastname Firstname Middlename 2 950000000 STAFF
25  * users 10 10 testacc 31275 sh cmd Lastname Firstname Middlename 1 950000000 STAFF testacc1 31275 sh cmd Lastname Firstname Middlename 1 950000000 STAFF
26  *   login, unix_uid, shell, winconsoleshell, last, first, middle, status, clearid, type
27  *
28  * test parameters for add member to group/list - done
29  * imembers 0 10 pismere-team USER dtanner 1 1 0 1 1 -1 1
30  * imembers 0 9 pismere-team STRING hope@ful.net 1 1 0 1 1 -1
31  *   list_name, user_type, name, active, publicflg, hidden, maillist, grouplist, gid
32  *
33  * test parameters for remove member from group/list - done
34  * imembers 10 0 pismere-team USER dtanner 1 1 0 1 1 -1 1
35  * imembers 9 0 pismere-team STRING hope@ful.net 1 1 0 1 1 -1
36  *   list_name, user_type, name, active, publicflg, hidden, maillist, grouplist, gid
37  *
38  * test parameters for creating and/or populating a group/list - done
39  * list 0 10 pismere-team 1 1 0 1 0 -1 USER 95260 description
40  *   name, active, publicflg, hidden, maillist, grouplist, gid, acl_type, acl_id, description
41  * 
42  * test parameters for deleting a group/list - done
43  * list 10 0 pismere-team 1 1 0 1 0 -1 USER 95260 description
44  *   name, active, publicflg, hidden, maillist, grouplist, gid, acl_type, acl_id, description
45  *
46  * test parameters for renaming a group/list - done
47  *  list 10 10 adtestlist 1 1 0 1 0 -1 USER 95260 description pismere-team 1 1 0 1 1 -1 USER 95260 description
48  *  list 10 10 pismere-team 1 1 0 1 1 -1 USER 95260 description adtestlist1 1 1 0 1 0 -1 USER 95260 description
49  *   name, active, publicflg, hidden, maillist, grouplist, gid, acl_type, acl_id, description
50 */
51 #include <mit-copyright.h>
52 #ifdef _WIN32
53 #include <windows.h>
54 #include <stdlib.h>
55 #include <malloc.h>
56 #include <lmaccess.h>
57 #endif
58 #include <hesiod.h>
59 #include <string.h>
60 #include <ldap.h>
61 #include <stdio.h>
62 #include <moira.h>
63 #include <moira_site.h>
64 #include <mrclient.h>
65 #include <krb5.h>
66 #include <krb.h>
67 #include <gsssasl.h>
68 #include <gssldap.h>
69 #include "kpasswd.h"
70
71 #ifdef _WIN32
72 #ifndef ECONNABORTED
73 #define ECONNABORTED WSAECONNABORTED
74 #endif
75 #ifndef ECONNREFUSED
76 #define ECONNREFUSED WSAECONNREFUSED
77 #endif
78 #ifndef EHOSTUNREACH
79 #define EHOSTUNREACH WSAEHOSTUNREACH
80 #endif
81 #define krb5_xfree free
82 #define F_OK 0
83 #define sleep(A) Sleep(A * 1000);
84 #endif /* _WIN32 */
85
86 #ifndef _WIN32
87 #include <sys/types.h>
88 #include <netinet/in.h>
89 #include <arpa/nameser.h>
90 #include <resolv.h>
91 #include <sys/utsname.h>
92 #include <unistd.h>
93
94 #define strnicmp(A,B,C) strncasecmp(A,B,C)
95 #define UCHAR unsigned char
96
97 #define UF_SCRIPT               0x0001
98 #define UF_ACCOUNTDISABLE       0x0002
99 #define UF_HOMEDIR_REQUIRED     0x0008
100 #define UF_LOCKOUT              0x0010
101 #define UF_PASSWD_NOTREQD       0x0020
102 #define UF_PASSWD_CANT_CHANGE   0x0040
103 #define UF_DONT_EXPIRE_PASSWD   0x10000
104
105 #define UF_TEMP_DUPLICATE_ACCOUNT       0x0100
106 #define UF_NORMAL_ACCOUNT               0x0200
107 #define UF_INTERDOMAIN_TRUST_ACCOUNT    0x0800
108 #define UF_WORKSTATION_TRUST_ACCOUNT    0x1000
109 #define UF_SERVER_TRUST_ACCOUNT         0x2000
110
111 #ifndef BYTE
112 #define BYTE unsigned char
113 #endif
114 typedef unsigned int DWORD;
115 typedef unsigned long ULONG;
116
117 typedef struct _GUID
118 {
119   unsigned long Data1;
120   unsigned short Data2;
121   unsigned short Data3;
122   unsigned char Data4[8];
123 } GUID;
124
125 typedef struct _SID_IDENTIFIER_AUTHORITY { 
126   BYTE Value[6]; 
127 } SID_IDENTIFIER_AUTHORITY, *PSID_IDENTIFIER_AUTHORITY; 
128
129 typedef struct _SID {
130   BYTE  Revision;
131   BYTE  SubAuthorityCount;
132   SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
133   DWORD SubAuthority[512];
134 } SID;
135 #endif/*!WIN32*/
136
137 #define AFS "/afs/"
138 #define WINAFS "\\\\afs\\all\\"
139
140 #define ADS_GROUP_TYPE_GLOBAL_GROUP         0x00000002
141 #define ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP   0x00000004
142 #define ADS_GROUP_TYPE_LOCAL_GROUP          0x00000004
143 #define ADS_GROUP_TYPE_UNIVERSAL_GROUP      0x00000008
144 #define ADS_GROUP_TYPE_SECURITY_ENABLED     0x80000000
145
146 #define QUERY_VERSION -1
147 #define PRIMARY_REALM "ATHENA.MIT.EDU"
148
149 #define SUBSTITUTE  1
150 #define REPLACE     2
151
152 #define USERS         0
153 #define GROUPS        1
154
155 #define MEMBER_ADD          1
156 #define MEMBER_REMOVE       2
157 #define MEMBER_CHANGE_NAME  3
158 #define MEMBER_ACTIVATE     4
159 #define MEMBER_DEACTIVATE   5
160 #define MEMBER_CREATE       6
161
162 #define MOIRA_ALL       0x0
163 #define MOIRA_USERS     0x1
164 #define MOIRA_KERBEROS  0x2
165 #define MOIRA_STRINGS   0x4
166 #define MOIRA_LISTS     0x8
167
168 #define ADFS_ADD    1
169 #define ADFS_DELETE 2
170
171 typedef struct lk_entry {
172   int     op;
173   int     length;
174   int     ber_value;
175   char    *dn;
176   char    *attribute;
177   char    *value;
178   char    *member;
179   char    *type;
180   char    *list;
181   struct  lk_entry *next;
182 } LK_ENTRY;
183
184 #define STOP_FILE "/moira/winad/nowinad"
185 #define file_exists(file) (access((file), F_OK) == 0)
186
187 #define LDAP_BERVAL struct berval
188 #define MAX_SERVER_NAMES 32
189
190 #define ADD_ATTR(t, v, o)               \
191   mods[n] = malloc(sizeof(LDAPMod));    \
192   mods[n]->mod_op = o;  \
193   mods[n]->mod_type = t;                \
194   mods[n++]->mod_values = v
195
196 LK_ENTRY *member_base = NULL;
197 LK_ENTRY *sid_base = NULL;
198 LK_ENTRY **sid_ptr = NULL;
199 static char tbl_buf[1024];
200 char  kerberos_ou[] = "OU=kerberos, OU=moira";
201 char  contact_ou[] = "OU=strings, OU=moira";
202 char  user_ou[] = "OU=users, OU=moira";
203 char  group_ou_distribution[] = "OU=mail, OU=lists, OU=moira";
204 char  group_ou_root[] = "OU=lists, OU=moira";
205 char  group_ou_security[] = "OU=group, OU=lists, OU=moira";
206 char  group_ou_neither[] = "OU=special, OU=lists, OU=moira";
207 char  group_ou_both[] = "OU=mail, OU=group, OU=lists, OU=moira";
208 char *whoami;
209 char group_manager[64];
210 char ldap_domain[256];
211 char list_type[32];
212 char GroupType[2];
213 int  maillist_flag;
214 int  group_flag;
215 int  mr_connections = 0;
216 int  callback_rc;
217 char default_server[256];
218 static char tbl_buf[1024];
219
220 extern int set_password(char *user, char *password, char *domain);
221
222 void AfsToWinAfs(char* path, char* winPath);
223 int ad_connect(LDAP **ldap_handle, char *ldap_domain, char *dn_path, 
224                char *Win2kPassword, char *Win2kUser, char *default_server,
225                int connect_to_kdc);
226 void ad_kdc_disconnect();
227 void check_winad(void);
228 void expand_groups(LDAP *ldap_handle, char *dn_path, char *group_name);
229 int filesys_process(int ac, char **av, void *ptr);
230 int user_create(int ac, char **av, void *ptr);
231 int user_change_status(int ac, char **av, void *ptr);
232 int user_delete(LDAP *ldap_handle, char *dn_path, char *u_name);
233 int user_rename(int ac, char **av, void *ptr);
234 int user_update(int ac, char **av, void *ptr);
235 int contact_create(LDAP *ld, char *bind_path, char *user, char *group_ou);
236 int get_group_info(int ac, char**av, void *ptr);
237 int group_create(int ac, char **av, void *ptr);
238 int group_delete(int ac, char **av, void *ptr);
239 int group_ad_delete(LDAP *ldap_handle, char *dn_path, char *group_name);
240 int group_list_build(int ac, char **av, void *ptr);
241 int group_rename(int ac, char **av, void *ptr);
242 int list_list_build(int ac, char **av, void *ptr);
243 int member_list_build(int ac, char **av, void *ptr);
244 int member_list_process(LDAP *ldap_handle, char *dn_path, char *group_name, 
245                         char *group_ou, char *group_membership, char *group_gid,
246                         int operation);
247 int member_remove(LDAP *ldap_handle, char *dn_path, char *group_name, 
248                   char *group_ou, char *group_membership, char *group_gid);
249 int sid_update(LDAP *ldap_handle, char *dn_path);
250 int check_string(char *s);
251 void convert_b_to_a(char *string, UCHAR *binary, int length);
252 int mr_connect_cl(char *server, char *client, int version, int auth);
253
254 void do_filesys(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
255              char **before, int beforec, char **after, int afterc);
256 void do_list(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
257              char **before, int beforec, char **after, int afterc);
258 void do_user(LDAP *ldap_handle, char *dn_path, char *ldap_hostname, 
259              char **before, int beforec, char **after, int afterc);
260 void do_member(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
261                char **before, int beforec, char **after, int afterc);
262 int linklist_create_entry(char *attribute, char *value,
263                           LK_ENTRY **linklist_entry);
264 int linklist_build(LDAP *ldap_handle, char *dn_path, char *search_exp, 
265                    char **attr_array, LK_ENTRY **linklist_base, 
266                    int *linklist_count);
267 void linklist_free(LK_ENTRY *linklist_base);
268
269 int retrieve_attributes(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
270                         char *distinguished_name, LK_ENTRY **linklist_current);
271 int retrieve_entries(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
272                      LK_ENTRY **linklist_base, int *linklist_count);
273 int retrieve_values(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
274                     char *Attribute, char *distinguished_name, 
275                     LK_ENTRY **linklist_current);
276
277 int construct_newvalues(LK_ENTRY *linklist_base, int modvalue_count, 
278                         char *oldValue, char *newValue,
279                         char ***modvalues, int type);
280 void free_values(char **modvalues);
281
282 int convert_domain_to_dn(char *domain, char **bind_path);
283 void get_distinguished_name(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
284                             char *distinguished_name);
285 int moira_disconnect(void);
286 int moira_connect(void);
287 void print_to_screen(const char *fmt, ...);
288
289 int main(int argc, char **argv)
290 {
291   unsigned long   rc;
292   int             beforec;
293   int             afterc;
294   int             i;
295   char            *table;
296   char            **before;
297   char            **after;
298   LDAP            *ldap_handle;
299   FILE            *fptr;
300   char            dn_path[256];
301
302   whoami = ((whoami = (char *)strrchr(argv[0], '/')) ? whoami+1 : argv[0]);
303
304   if (argc < 4)
305     {
306       com_err(whoami, 0, "%s", "argc < 4");
307       exit(1);
308     }
309   beforec = atoi(argv[2]);
310   afterc = atoi(argv[3]);
311
312   if (argc < (4 + beforec + afterc))
313     {
314       com_err(whoami, 0, "%s", "argc < (4 + breforec + afterc)");
315       exit(1);
316     }
317
318   table = argv[1];
319   before = &argv[4];
320   after = &argv[4 + beforec];
321
322   for (i = 1; i < argc; i++)
323     {
324       strcat(tbl_buf, argv[i]);
325       strcat(tbl_buf, " ");
326     }
327   com_err(whoami, 0, "%s", tbl_buf);
328
329   check_winad();
330   
331   memset(ldap_domain, '\0', sizeof(ldap_domain));
332   if ((fptr = fopen("/moira/winad/winad.cfg", "r")) != NULL)
333     {
334       fread(ldap_domain, sizeof(char), sizeof(ldap_domain), fptr);
335       fclose(fptr);
336     }
337   if (strlen(ldap_domain) == 0)
338     strcpy(ldap_domain, "win.mit.edu");
339   initialize_sms_error_table();
340   initialize_krb_error_table();
341
342   memset(default_server, '\0', sizeof(default_server));
343   memset(dn_path, '\0', sizeof(dn_path));
344   if (ad_connect(&ldap_handle, ldap_domain, dn_path, "", "", default_server, 1))
345     {
346       com_err(whoami, 0, "%s %s", "cannot connect to any server in domain ",
347               ldap_domain);
348       exit(1);
349     }
350
351   for (i = 0; i < (int)strlen(table); i++)
352     table[i] = tolower(table[i]);
353   if (!strcmp(table, "users"))
354     do_user(ldap_handle, dn_path, ldap_domain, before, beforec, after,
355             afterc);
356   else if (!strcmp(table, "list"))
357     do_list(ldap_handle, dn_path, ldap_domain, before, beforec, after,
358             afterc);
359   else if (!strcmp(table, "imembers"))
360     do_member(ldap_handle, dn_path, ldap_domain, before, beforec, after,
361               afterc);
362   else if (!strcmp(table, "filesys"))
363     do_filesys(ldap_handle, dn_path, ldap_domain, before, beforec, after,
364                afterc);
365 /*
366   else if (!strcmp(table, "quota"))
367     do_quota(before, beforec, after, afterc);
368 */
369
370   ad_kdc_disconnect();
371   rc = ldap_unbind_s(ldap_handle);
372   exit(0);
373 }
374
375 void do_filesys(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
376              char **before, int beforec, char **after, int afterc)
377 {
378   long  rc;
379   char  *av[3];
380   char  *call_args[7];
381   int   acreate;
382   int   atype;
383   int   bcreate;
384   int   btype;
385
386   if (rc = moira_connect())
387     {
388       critical_alert("AD incremental",
389                      "Error contacting Moira server : %s",
390                      error_message(rc));
391       return;
392     }
393
394   if (afterc < FS_CREATE)
395     atype = acreate = 0;
396   else
397     {
398       atype = !strcmp(after[FS_TYPE], "AFS");
399       acreate = atoi(after[FS_CREATE]);
400     }
401
402   if (beforec < FS_CREATE)
403     {
404       if (acreate == 0 || atype == 0)
405         goto cleanup;
406       com_err(whoami, 0, "Processing filesys %s", after[FS_NAME]);
407       av[0] = after[FS_NAME];
408       call_args[0] = (char *)ldap_handle;
409       call_args[1] = dn_path;
410       call_args[2] = after[FS_NAME];
411       call_args[3] = (char *)ADFS_ADD;
412       if (rc = mr_query("get_filesys_by_label", 1, av, filesys_process, call_args))
413         {
414           critical_alert("AD incremental", "Couldn't process filesys %s : %s",
415                           after[FS_NAME], error_message(rc));
416           goto cleanup;
417         }
418       goto cleanup;
419     }
420
421   btype = !strcmp(before[FS_TYPE], "AFS");
422   bcreate = atoi(before[FS_CREATE]);
423   if (afterc < FS_CREATE)
424     {
425       if (btype && bcreate)
426         {
427           av[0] = before[FS_NAME];
428           av[1] = before[FS_TYPE];
429           call_args[0] = (char *)ldap_handle;
430           call_args[1] = dn_path;
431           call_args[2] = before[FS_NAME];
432           call_args[3] = (char *)ADFS_DELETE;
433           if (filesys_process(beforec, before, (void *)call_args))
434             {
435               critical_alert("AD incremental", "Couldn't delete filesys %s : %s",
436                              before[FS_NAME], error_message(rc));
437             }
438         }
439       goto cleanup;
440     }
441
442   if (!acreate)
443     goto cleanup;
444
445   if (!atype && !btype)
446     {
447       if (strcmp(before[FS_TYPE], "ERR") || strcmp(after[FS_TYPE], "ERR"))
448         {
449           critical_alert("incremental", "Filesystem %s or %s is not AFS: "
450                          "Operation not supported", before[FS_NAME], after[FS_NAME]);
451           goto cleanup;
452         }
453     }
454   com_err(whoami, 0, "Processing filesys %s", after[FS_NAME]);
455   av[0] = after[FS_NAME];
456   call_args[0] = (char *)ldap_handle;
457   call_args[1] = dn_path;
458   call_args[2] = after[FS_NAME];
459   call_args[3] = (char *)ADFS_ADD;
460   if (rc = mr_query("get_filesys_by_label", 1, av, filesys_process, call_args))
461     {
462       critical_alert("AD incremental", "Couldn't process filesys %s : %s",
463                      after[FS_NAME], error_message(rc));
464       goto cleanup;
465     }
466 cleanup:
467   moira_disconnect();
468   return;
469 }
470 void do_list(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
471              char **before, int beforec, char **after, int afterc)
472 {
473   int     ahide;
474   int     bhide;
475   int     apublic;
476   int     bpublic;
477   int     bgroup;
478   int     agroup;
479   int     amaillist;
480   int     bmaillist;
481   int     bstatus;
482   int     astatus;
483   long    rc;
484   char    *av[3];
485   char    *call_args[7];
486
487   if (beforec == 0 && afterc == 0)
488     return;
489
490   astatus = bstatus = 0;
491   ahide = bhide = 0;
492   apublic = bpublic = 0;
493   amaillist = bmaillist = 0;
494   if (beforec != 0)
495     {
496       if (atoi(before[L_ACTIVE]))
497         {
498           bstatus = atoi(before[L_ACTIVE]);
499           bhide = atoi(before[L_HIDDEN]);
500           bpublic = atoi(before[L_PUBLIC]);
501           bmaillist = atoi(before[L_MAILLIST]);
502           bgroup = atoi(before[L_GROUP]);
503         }
504      }
505   if (afterc != 0)
506     {
507       if (atoi(after[L_ACTIVE]))
508         {
509           astatus = atoi(after[L_ACTIVE]);
510           ahide = atoi(after[L_HIDDEN]);
511           apublic = atoi(after[L_PUBLIC]);
512           amaillist = atoi(after[L_MAILLIST]);
513           agroup = atoi(after[L_GROUP]);
514         }
515     }
516
517   if (rc = moira_connect())
518     {
519       critical_alert("AD incremental",
520                      "Error contacting Moira server : %s",
521                      error_message(rc));
522       return;
523     }
524
525   if (astatus && bstatus)
526     {
527       if ((bmaillist == amaillist) && (bgroup == agroup) &&
528           (!strcmp(before[L_NAME], after[L_NAME])))
529         return;
530       com_err(whoami, 0, "Changing group %s to %s",
531               before[L_NAME], after[L_NAME]);
532
533       av[0] = after[L_NAME];
534       call_args[0] = (char *)ldap_handle;
535       call_args[1] = dn_path;
536       call_args[2] = before[L_NAME];
537       call_args[3] = before[L_MAILLIST];
538       call_args[4] = before[L_GROUP];
539       call_args[5] = NULL;
540       callback_rc = 0;
541       if (rc = mr_query("get_list_info", 1, av, group_rename, call_args))
542         {
543            if (callback_rc != LDAP_NO_SUCH_OBJECT)
544              {
545                critical_alert("AD incremental",
546                               "Could not change list %s to %s : %s",
547                               before[L_NAME], 
548                               after[L_NAME], error_message(rc));
549                goto cleanup;
550              }
551            callback_rc = LDAP_NO_SUCH_OBJECT;
552          }
553       if (callback_rc != LDAP_NO_SUCH_OBJECT)
554         goto cleanup;
555       bstatus = 0;
556     }
557   if (bstatus)
558     {
559       com_err(whoami, 0, "Deleting group %s", before[L_NAME]);
560       rc = group_ad_delete(ldap_handle, dn_path, before[L_NAME]);
561       goto cleanup;
562     }
563   if (astatus)
564     {
565       com_err(whoami, 0, "Creating group %s", after[L_NAME]);
566
567       sleep(1);
568       av[0] = after[L_NAME];
569       call_args[0] = (char *)ldap_handle;
570       call_args[1] = dn_path;
571       call_args[2] = after[L_NAME];
572       call_args[3] = NULL;
573       call_args[4] = NULL;
574       call_args[5] = NULL;
575       call_args[6] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
576       sid_base = NULL;
577       sid_ptr = &sid_base;
578       if (rc = mr_query("get_list_info", 1, av, group_create, call_args))
579         {
580           critical_alert("AD incremental", "Couldn't create list %s : %s",
581                          after[L_NAME], error_message(rc));
582             goto cleanup;
583         }
584       if ((call_args[3] == NULL) || (call_args[4] == NULL) || (call_args[5] == NULL))
585         {
586           linklist_free(member_base);
587           linklist_free(sid_base);
588           sid_base = NULL;
589           member_base = NULL;
590           goto cleanup;
591         }
592       if (sid_base != NULL)
593         {
594           sid_update(ldap_handle, dn_path);
595           linklist_free(sid_base);
596           sid_base = NULL;
597         }
598
599       if (afterc == 0)
600         goto cleanup;
601       sleep(1);
602
603       member_base = NULL;
604       if (!(rc = mr_query("get_end_members_of_list", 1, av, member_list_build,
605                           call_args)))
606         {
607           if (member_base != NULL)
608             {
609               rc = member_list_process(ldap_handle, dn_path, after[L_NAME],
610                                        call_args[3], call_args[4], call_args[5],
611                                        MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
612               expand_groups(ldap_handle, dn_path, after[L_NAME]);
613             }
614         }
615       else
616         {
617           critical_alert("AD incremental",
618                          "Error contacting Moira server to resolve %s : %s",
619                          after[L_NAME], error_message(rc));
620         }
621       linklist_free(member_base);
622       member_base = NULL;
623       goto cleanup;
624     }
625 cleanup:
626   moira_disconnect();
627 }
628
629 #define LM_EXTRA_ACTIVE  (LM_END)
630
631 void do_member(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
632                char **before, int beforec, char **after, int afterc)
633 {
634   char  *call_args[7];
635   char  *av[2];
636   char  group_name[128];
637   char  user_name[128];
638   char  user_type[128];
639   int   rc;
640
641   if (afterc)
642     {
643       if (!atoi(after[LM_EXTRA_ACTIVE]))
644         return;
645       strcpy(user_name, after[LM_MEMBER]);
646       strcpy(group_name, after[LM_LIST]);
647       strcpy(user_type, after[LM_TYPE]);
648
649     }
650   else if (beforec)
651     {
652       if (!atoi(before[LM_EXTRA_ACTIVE]))
653           return;
654       strcpy(user_name, before[LM_MEMBER]);
655       strcpy(group_name, before[LM_LIST]);
656       strcpy(user_type, before[LM_TYPE]);
657     }
658
659   if (rc = moira_connect())
660     {
661       critical_alert("AD incremental", 
662                      "Moira error retrieving grouplist of user %s : %s",
663                      user_name, error_message(rc));
664       return;
665     }
666   com_err(whoami, 0, "Updating list %s membership for user %s.", group_name,
667           user_name);
668   av[0] = group_name;
669   call_args[0] = (char *)ldap_handle;
670   call_args[1] = dn_path;
671   call_args[2] = group_name;
672   call_args[3] = NULL;
673   call_args[4] = NULL;
674   call_args[5] = NULL;
675   call_args[6] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
676   member_base = NULL;
677   sid_base = NULL;
678   sid_ptr = &sid_base;
679   if (!(rc = mr_query("get_list_info", 1, av, group_create, call_args)))
680     {
681       rc = 1;
682       if ((call_args[3] != NULL) && (call_args[4] != NULL) && (call_args[5]
683 = NULL))
684         {
685           rc = 0;
686           if (sid_base != NULL)
687             {
688               sid_update(ldap_handle, dn_path);
689               linklist_free(sid_base);
690               sid_base = NULL;
691             }
692           member_base = NULL;
693           sleep(1);
694
695           if (!(rc = mr_query("get_end_members_of_list", 1, av, member_list_build,
696                               call_args)))
697             {
698               if (member_base == NULL)
699                 {
700                   member_remove(ldap_handle, dn_path, group_name,
701                                 call_args[3], call_args[4], call_args[5]);
702                 }
703               else
704                 {
705                   rc = member_list_process(ldap_handle, dn_path, group_name,
706                                            call_args[3], call_args[4], call_args[5],
707                                            MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
708                   expand_groups(ldap_handle, dn_path, group_name);
709                 }
710             }
711         }
712     }
713   if (rc)
714     {
715       if (afterc)
716         critical_alert("AD incremental", "Couldn't add %s to group %s ",
717                        user_name, group_name);
718       else
719         critical_alert("AD incremental", "Couldn't remove %s from group %s ",
720                        user_name, group_name);
721     }
722   linklist_free(member_base);
723   linklist_free(sid_base);
724   member_base = NULL;
725   if (call_args[3] != NULL)
726     free(call_args[3]);
727   if (call_args[4] != NULL)
728     free(call_args[4]);
729   moira_disconnect();
730 }
731
732
733 void do_user(LDAP *ldap_handle, char *dn_path, char *ldap_hostname, 
734              char **before, int beforec, char **after, 
735              int afterc)
736 {
737   int   rc;
738   char  *av[2];
739   char  *call_args[6];
740   int   astate;
741   int   bstate;
742
743   if ((beforec == 0) || (afterc == 0))
744     return;
745
746   astate = 0;
747   bstate = 0;
748   if (afterc > U_STATE)
749     astate = atoi(after[U_STATE]);
750   if (beforec > U_STATE)
751     bstate = atoi(before[U_STATE]);
752
753   if (astate == 2)
754     astate = 1;
755   if (bstate == 2)
756     bstate = 1;
757
758   if ((bstate == 0) && (astate == 0))
759     return;
760
761   if (rc = moira_connect())
762     {
763       critical_alert("AD incremental", 
764                      "Error connection to Moira : %s",
765                      error_message(rc));
766       return;
767     }
768
769   if (astate == bstate)
770     {
771       if (!strcmp(before[U_NAME], after[U_NAME]))
772         {
773           com_err(whoami, 0, "Updating user %s info", before[U_NAME]);
774           av[0] = before[U_NAME];
775           call_args[0] = (char *)ldap_handle;
776           call_args[1] = dn_path;
777           sid_base = NULL;
778           sid_ptr = &sid_base;
779           callback_rc = 0;
780           if (rc = mr_query("get_user_account_by_login", 1, av, user_update,
781                             call_args))
782             {
783               if (callback_rc != LDAP_NO_SUCH_OBJECT)
784                 {
785                   critical_alert("AD incremental",
786                                  "Could not update user %s info : %s",
787                                  before[U_NAME], 
788                                  error_message(rc));
789                   goto cleanup;
790                 }
791             }
792         }
793       else
794         {
795           com_err(whoami, 0, "Changing user %s to %s", before[U_NAME],
796                   after[U_NAME]);
797           av[0] = after[U_NAME];
798           call_args[0] = (char *)ldap_handle;
799           call_args[1] = dn_path;
800           call_args[2] = (char *)MEMBER_ACTIVATE;
801           call_args[3] = before[U_NAME];
802           sid_base = NULL;
803           sid_ptr = &sid_base;
804           callback_rc = 0;
805           if (rc = mr_query("get_user_account_by_login", 1, av, user_rename,
806                             call_args))
807             {
808               if (callback_rc != LDAP_NO_SUCH_OBJECT)
809                 {
810                   critical_alert("AD incremental",
811                                  "Could not change user %s to %s : %s",
812                                  before[U_NAME], 
813                                  after[U_NAME], error_message(rc));
814                   goto cleanup;
815                 }
816             }
817         }
818       if (callback_rc != LDAP_NO_SUCH_OBJECT)
819         goto cleanup;
820       bstate = 0;
821     }
822   if (bstate == 1)
823     {
824       com_err(whoami, 0, "Deactivate user %s in the AD", before[U_NAME]);
825       av[0] = before[U_NAME];
826       call_args[0] = (char *)ldap_handle;
827       call_args[1] = dn_path;
828       call_args[2] = (char *)MEMBER_DEACTIVATE;
829       if (rc = mr_query("get_user_account_by_login", 1, av, user_change_status,
830                         call_args))
831         {
832           critical_alert("AD incremental",
833                          "Couldn't deactivate user %s in the AD : %s",
834                          before[U_NAME], error_message(rc));
835         }
836       goto cleanup;
837     }
838   if (astate == 1)
839     {
840       com_err(whoami, 0, "%s user %s", "Creating/Reactivating",
841               after[U_NAME]);
842
843       av[0] = after[U_NAME];
844       call_args[0] = (char *)ldap_handle;
845       call_args[1] = dn_path;
846       call_args[2] = (char *)MEMBER_ACTIVATE;
847       call_args[3] = NULL;
848       sid_base = NULL;
849       sid_ptr = &sid_base;
850       if (rc = mr_query("get_user_account_by_login", 1, av, user_create,
851                         call_args))
852         {
853           critical_alert("AD incremental", "Couldn't create/activate user %s : %s",
854                          after[U_NAME], error_message(rc));
855           goto cleanup;
856         }
857       if (sid_base != NULL)
858         {
859           sid_update(ldap_handle, dn_path);
860           linklist_free(sid_base);
861         }
862     }
863 cleanup:
864   moira_disconnect();
865 }
866
867 int construct_newvalues(LK_ENTRY *linklist_base, int modvalue_count, 
868                         char *oldValue, char *newValue,
869                         char ***modvalues, int type)
870 {
871   LK_ENTRY    *linklist_ptr;
872   int         i;
873   char        *cPtr;
874
875   if (((*modvalues) = calloc(1, (modvalue_count + 1) * sizeof(char *)))
876       == NULL)
877     {
878       return(1);
879     }
880   for (i = 0; i < (modvalue_count + 1); i++)
881     (*modvalues)[i] = NULL;
882   if (modvalue_count != 0)
883     {
884       linklist_ptr = linklist_base;
885       for (i = 0; i < modvalue_count; i++)
886         {
887           if ((oldValue != NULL) && (newValue != NULL))
888             {
889               if ((cPtr = (char *)strstr(linklist_ptr->value, oldValue))
890                  != (char *)NULL)
891                 {
892                   if (type == REPLACE)
893                     {
894                       if (((*modvalues)[i] = calloc(1, strlen(newValue) + 1))
895                           == NULL)
896                         return(1);
897                       memset((*modvalues)[i], '\0', strlen(newValue) + 1);
898                       strcpy((*modvalues)[i], newValue);
899                     }
900                   else
901                     {
902                       if (((*modvalues)[i] = calloc(1, 
903                                         (int)(cPtr - linklist_ptr->value) + 
904                                         (linklist_ptr->length - strlen(oldValue)) + 
905                                         strlen(newValue) + 1)) == NULL)
906                         return(1);
907                       memset((*modvalues)[i], '\0', 
908                              (int)(cPtr - linklist_ptr->value) + 
909                              (linklist_ptr->length - strlen(oldValue)) + 
910                              strlen(newValue) + 1);
911                       memcpy((*modvalues)[i], linklist_ptr->value, 
912                              (int)(cPtr - linklist_ptr->value));
913                       strcat((*modvalues)[i], newValue);
914                       strcat((*modvalues)[i], 
915      &linklist_ptr->value[(int)(cPtr - linklist_ptr->value) + strlen(oldValue)]);
916                     }
917                 }
918               else
919                 {
920                   (*modvalues)[i] = calloc(1, linklist_ptr->length + 1);
921                   memset((*modvalues)[i], '\0', linklist_ptr->length + 1);
922                   memcpy((*modvalues)[i], linklist_ptr->value,
923                          linklist_ptr->length);
924                 }
925             }
926         else
927             {
928               (*modvalues)[i] = calloc(1, linklist_ptr->length + 1);
929               memset((*modvalues)[i], '\0', linklist_ptr->length + 1);
930               memcpy((*modvalues)[i], linklist_ptr->value,
931                      linklist_ptr->length);
932             }
933           linklist_ptr = linklist_ptr->next;
934         }
935       (*modvalues)[i] = NULL;
936     }
937   return(0);
938 }
939
940
941 int linklist_build(LDAP *ldap_handle, char *dn_path, char *search_exp, 
942                    char **attr_array, LK_ENTRY **linklist_base,
943                    int *linklist_count)
944 {
945   ULONG       rc;
946   LDAPMessage *ldap_entry;
947
948   rc = 0;
949   ldap_entry = NULL;
950   (*linklist_base) = NULL;
951   (*linklist_count) = 0;
952   if ((rc = ldap_search_s(ldap_handle, dn_path, LDAP_SCOPE_SUBTREE, 
953                           search_exp, attr_array, 0, &ldap_entry))
954       != LDAP_SUCCESS)
955     return(0);
956   rc = retrieve_entries(ldap_handle, ldap_entry, linklist_base, linklist_count);
957
958   ldap_msgfree(ldap_entry);
959   return(rc);
960 }
961
962
963 int retrieve_entries(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
964                      LK_ENTRY **linklist_base, int *linklist_count)
965 {
966   char        distinguished_name[1024];
967   LK_ENTRY    *linklist_ptr;
968   int         rc;
969
970   if ((ldap_entry = ldap_first_entry(ldap_handle, ldap_entry)) == NULL)
971     return(0);
972
973   memset(distinguished_name, '\0', sizeof(distinguished_name));
974   get_distinguished_name(ldap_handle, ldap_entry, distinguished_name);
975
976   if ((rc = retrieve_attributes(ldap_handle, ldap_entry, distinguished_name,
977                                 linklist_base)) != 0)
978     return(rc);
979
980   while ((ldap_entry = ldap_next_entry(ldap_handle, ldap_entry)) != NULL)
981     {
982       memset(distinguished_name, '\0', sizeof(distinguished_name));
983       get_distinguished_name(ldap_handle, ldap_entry, distinguished_name);
984
985       if ((rc = retrieve_attributes(ldap_handle, ldap_entry, distinguished_name,
986                                     linklist_base)) != 0)
987         return(rc);
988     }
989
990   linklist_ptr = (*linklist_base);
991   (*linklist_count) = 0;
992   while (linklist_ptr != NULL)
993     {
994       ++(*linklist_count);
995       linklist_ptr = linklist_ptr->next;
996     }
997   return(0);
998 }
999
1000 int retrieve_attributes(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
1001                         char *distinguished_name, LK_ENTRY **linklist_current)
1002 {
1003   char        *Attribute;
1004   BerElement  *ptr;
1005
1006   ptr = NULL;
1007   if ((Attribute = ldap_first_attribute(ldap_handle, ldap_entry, &ptr)) != NULL)
1008     {
1009       retrieve_values(ldap_handle, ldap_entry, Attribute, distinguished_name,
1010                       linklist_current);
1011       ldap_memfree(Attribute);
1012       while ((Attribute = ldap_next_attribute(ldap_handle, ldap_entry, 
1013                                               ptr)) != NULL)
1014         {
1015           retrieve_values(ldap_handle, ldap_entry, Attribute,
1016                           distinguished_name, linklist_current);
1017           ldap_memfree(Attribute);
1018         }
1019     }
1020   ldap_ber_free(ptr, 0);
1021   return(0);
1022 }
1023
1024 int retrieve_values(LDAP *ldap_handle, LDAPMessage *ldap_entry,
1025                     char *Attribute, char *distinguished_name,
1026                     LK_ENTRY **linklist_current)
1027 {
1028   char        **str_value;
1029   char        temp[256];
1030   void        **Ptr;
1031   int         use_bervalue;
1032   LK_ENTRY    *linklist_previous;
1033   LDAP_BERVAL **ber_value;
1034   DWORD       ber_length;
1035 #ifdef LDAP_DEBUG
1036   SID         *sid;
1037   GUID        *guid;
1038   int         i;
1039   int         intValue;
1040   DWORD       *subauth;
1041   SID_IDENTIFIER_AUTHORITY    *sid_auth;
1042   unsigned char   *subauth_count;
1043 #endif /*LDAP_BEGUG*/
1044
1045   use_bervalue = 0;
1046   memset(temp, '\0', sizeof(temp));
1047   if ((!strcmp(Attribute, "objectSid")) ||
1048       (!strcmp(Attribute, "objectGUID")))
1049     use_bervalue = 1;
1050
1051   if (use_bervalue)
1052     {
1053       ber_value = ldap_get_values_len(ldap_handle, ldap_entry, Attribute);
1054       Ptr = (void **)ber_value;
1055       str_value = NULL;
1056       }
1057   else
1058     {
1059       str_value = ldap_get_values(ldap_handle, ldap_entry, Attribute);
1060       Ptr = (void **)str_value;
1061       ber_value = NULL;
1062     }
1063   if (Ptr != NULL)
1064     {
1065       for (; *Ptr; Ptr++) 
1066         {
1067           if ((linklist_previous = calloc(1, sizeof(LK_ENTRY))) == NULL)
1068             return(1);
1069           memset(linklist_previous, '\0', sizeof(LK_ENTRY));
1070           linklist_previous->next = (*linklist_current);
1071           (*linklist_current) = linklist_previous;
1072
1073           if (((*linklist_current)->attribute = calloc(1, 
1074                                                strlen(Attribute) + 1)) == NULL)
1075             return(1);
1076           memset((*linklist_current)->attribute, '\0', strlen(Attribute) + 1);
1077           strcpy((*linklist_current)->attribute, Attribute);
1078           if (use_bervalue)
1079             {
1080               ber_length = (*(LDAP_BERVAL **)Ptr)->bv_len;
1081               if (((*linklist_current)->value = calloc(1, ber_length)) == NULL)
1082                 return(1);
1083               memset((*linklist_current)->value, '\0', ber_length);
1084               memcpy((*linklist_current)->value, (*(LDAP_BERVAL **)Ptr)->bv_val, 
1085                                                   ber_length);
1086               (*linklist_current)->length = ber_length;
1087             }
1088           else
1089             {
1090               if (((*linklist_current)->value = calloc(1, 
1091                                                   strlen(*Ptr) + 1)) == NULL)
1092                 return(1);
1093               memset((*linklist_current)->value, '\0', strlen(*Ptr) + 1);
1094               (*linklist_current)->length = strlen(*Ptr);
1095               strcpy((*linklist_current)->value, *Ptr);
1096             }
1097           (*linklist_current)->ber_value = use_bervalue;
1098           if (((*linklist_current)->dn = calloc(1, 
1099                                       strlen(distinguished_name) + 1)) == NULL)
1100             return(1);
1101           memset((*linklist_current)->dn, '\0', strlen(distinguished_name) + 1);
1102           strcpy((*linklist_current)->dn, distinguished_name);
1103
1104 #ifdef LDAP_DEBUG
1105           if (!strcmp(Attribute, "objectGUID"))
1106             {
1107               guid = (GUID *)((*linklist_current)->value);
1108               sprintf(temp, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 
1109                       guid->Data1, guid->Data2, guid->Data3, 
1110                       guid->Data4[0], guid->Data4[1], guid->Data4[2], 
1111                       guid->Data4[3], guid->Data4[4], guid->Data4[5], 
1112                       guid->Data4[6], guid->Data4[7]);
1113               print_to_screen("     %20s : {%s}\n", Attribute, temp);
1114             }
1115           else if (!strcmp(Attribute, "objectSid"))
1116             {
1117               sid = (SID *)((*(LDAP_BERVAL **)Ptr)->bv_val);
1118 #ifdef _WIN32
1119               print_to_screen("        Revision = %d\n", sid->Revision);
1120               print_to_screen("        SID Identifier Authority:\n");
1121               sid_auth = &sid->IdentifierAuthority;
1122               if (sid_auth->Value[0])
1123                 print_to_screen("            SECURITY_NULL_SID_AUTHORITY\n");
1124               else if (sid_auth->Value[1])
1125                 print_to_screen("            SECURITY_WORLD_SID_AUTHORITY\n");
1126               else if (sid_auth->Value[2])
1127                 print_to_screen("            SECURITY_LOCAL_SID_AUTHORITY\n");
1128               else if (sid_auth->Value[3])
1129                 print_to_screen("            SECURITY_CREATOR_SID_AUTHORITY\n");
1130               else if (sid_auth->Value[5])
1131                 print_to_screen("            SECURITY_NT_AUTHORITY\n");
1132               else
1133                 print_to_screen("            UNKNOWN SID AUTHORITY\n");
1134               subauth_count = GetSidSubAuthorityCount(sid);
1135               print_to_screen("        SidSubAuthorityCount = %d\n", 
1136                               *subauth_count);
1137               print_to_screen("        SidSubAuthority:\n");
1138               for (i = 0; i < *subauth_count; i++)
1139                 {
1140                   if ((subauth = GetSidSubAuthority(sid, i)) != NULL)
1141                     print_to_screen("            %u\n", *subauth);
1142                 }
1143 #endif
1144             }
1145           else if ((!memcmp(Attribute, "userAccountControl", 
1146                             strlen("userAccountControl"))) ||
1147                    (!memcmp(Attribute, "sAMAccountType", 
1148                             strlen("sAmAccountType"))))
1149             {
1150               intValue = atoi(*Ptr);
1151               print_to_screen("     %20s : %ld\n",Attribute, intValue);
1152               if (!memcmp(Attribute, "userAccountControl", 
1153                           strlen("userAccountControl")))
1154                 {
1155                   if (intValue & UF_ACCOUNTDISABLE)
1156                     print_to_screen("     %20s :    %s\n", 
1157                                     "", "Account disabled");
1158                   else
1159                     print_to_screen("     %20s :    %s\n", 
1160                                     "", "Account active");
1161                   if (intValue & UF_HOMEDIR_REQUIRED)
1162                     print_to_screen("     %20s :    %s\n", 
1163                                     "", "Home directory required");
1164                   if (intValue & UF_LOCKOUT)
1165                     print_to_screen("     %20s :    %s\n", 
1166                                     "", "Account locked out");
1167                   if (intValue & UF_PASSWD_NOTREQD)
1168                     print_to_screen("     %20s :    %s\n", 
1169                                     "", "No password required");
1170                   if (intValue & UF_PASSWD_CANT_CHANGE)
1171                     print_to_screen("     %20s :    %s\n",
1172                                     "", "Cannot change password");
1173                   if (intValue & UF_TEMP_DUPLICATE_ACCOUNT)
1174                     print_to_screen("     %20s :    %s\n", 
1175                                     "", "Temp duplicate account");
1176                   if (intValue & UF_NORMAL_ACCOUNT)
1177                     print_to_screen("     %20s :    %s\n", 
1178                                     "", "Normal account");
1179                   if (intValue & UF_INTERDOMAIN_TRUST_ACCOUNT)
1180                     print_to_screen("     %20s :    %s\n", 
1181                                     "", "Interdomain trust account");
1182                   if (intValue & UF_WORKSTATION_TRUST_ACCOUNT)
1183                     print_to_screen("     %20s :    %s\n", 
1184                                     "", "Workstation trust account");
1185                   if (intValue & UF_SERVER_TRUST_ACCOUNT)
1186                     print_to_screen("     %20s :    %s\n", 
1187                                     "", "Server trust account");
1188                 }
1189             }
1190           else
1191             {
1192               print_to_screen("     %20s : %s\n",Attribute, *Ptr);
1193             }
1194 #endif /*LDAP_DEBUG*/
1195         }
1196       if (str_value != NULL)
1197         ldap_value_free(str_value);
1198       if (ber_value != NULL)
1199         ldap_value_free_len(ber_value);
1200     }
1201   (*linklist_current) = linklist_previous;
1202   return(0);
1203 }
1204
1205 int moira_connect(void)
1206 {
1207   long    rc;
1208   char    HostName[64];
1209
1210   if (!mr_connections++)
1211     {
1212 #ifdef _WIN32
1213       memset(HostName, '\0', sizeof(HostName));
1214       strcpy(HostName, "ttsp");
1215       rc = mr_connect_cl(HostName, "winad.incr", QUERY_VERSION, 1);
1216 /*det
1217       rc = mr_connect(HostName);
1218 */
1219 #else
1220       struct utsname uts;
1221       uname(&uts);
1222       rc = mr_connect_cl(uts.nodename, "winad.incr", QUERY_VERSION, 1);
1223 /*
1224       rc = mr_connect(uts.nodename);
1225 */
1226 #endif /*WIN32*/
1227 /*det
1228       if (!rc)
1229         rc = mr_auth("winad.incr");
1230 */
1231       return rc;
1232     }
1233   return 0;
1234 }
1235
1236 void check_winad(void)
1237 {
1238   int i;
1239   
1240   for (i = 0; file_exists(STOP_FILE); i++)
1241     {
1242       if (i > 30)
1243         {
1244           critical_alert("incremental",
1245                          "WINAD incremental failed (%s exists): %s",
1246                          STOP_FILE, tbl_buf);
1247           exit(1);
1248         }
1249       sleep(60);
1250     }
1251 }
1252
1253 int moira_disconnect(void)
1254 {
1255
1256   if (!--mr_connections)
1257     {
1258       mr_disconnect();
1259     }
1260   return 0;
1261 }
1262
1263 void get_distinguished_name(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
1264                             char *distinguished_name)
1265 {
1266   char    *CName;
1267
1268   CName = ldap_get_dn(ldap_handle, ldap_entry);
1269   if (CName == NULL)
1270     return;
1271   strcpy(distinguished_name, CName);
1272   ldap_memfree(CName);
1273 }
1274
1275 int linklist_create_entry(char *attribute, char *value, 
1276                           LK_ENTRY **linklist_entry)
1277 {
1278   (*linklist_entry) = calloc(1, sizeof(LK_ENTRY));
1279   if (!(*linklist_entry))
1280     {
1281       return(1);
1282     }
1283   memset((*linklist_entry), '\0', sizeof(LK_ENTRY));
1284   (*linklist_entry)->attribute = calloc(1, strlen(attribute) + 1);
1285   memset((*linklist_entry)->attribute, '\0', strlen(attribute) + 1);
1286   strcpy((*linklist_entry)->attribute, attribute);
1287   (*linklist_entry)->value = calloc(1, strlen(value) + 1);
1288   memset((*linklist_entry)->value, '\0', strlen(value) + 1);
1289   strcpy((*linklist_entry)->value, value);
1290   (*linklist_entry)->length = strlen(value);
1291   (*linklist_entry)->next = NULL;
1292   return(0);
1293 }
1294
1295 void print_to_screen(const char *fmt, ...)
1296 {
1297   va_list pvar;
1298
1299   va_start(pvar, fmt);
1300   vfprintf(stderr, fmt, pvar);
1301   fflush(stderr);
1302   va_end(pvar);
1303 }
1304
1305 int get_group_membership(char *group_membership, char *group_ou, 
1306                          int *security_flag, char **av)
1307 {
1308   int  maillist_flag;
1309   int  group_flag;
1310
1311   maillist_flag = atoi(av[L_MAILLIST]);
1312   group_flag = atoi(av[L_GROUP]);
1313   if (security_flag != NULL)
1314     (*security_flag) = 0;
1315
1316   if ((maillist_flag) && (group_flag))
1317     {
1318       if (group_membership != NULL)
1319         group_membership[0] = 'B';
1320       if (security_flag != NULL)
1321         (*security_flag) = 1;
1322       if (group_ou != NULL)
1323         strcpy(group_ou, group_ou_both);
1324     }
1325   else if ((!maillist_flag) && (group_flag))
1326     {
1327       if (group_membership != NULL)
1328         group_membership[0] = 'S';
1329       if (security_flag != NULL)
1330         (*security_flag) = 1;
1331       if (group_ou != NULL)
1332         strcpy(group_ou, group_ou_security);
1333     }
1334   else if ((maillist_flag) && (!group_flag))
1335     {
1336       if (group_membership != NULL)
1337         group_membership[0] = 'D';
1338       if (group_ou != NULL)
1339         strcpy(group_ou, group_ou_distribution);
1340     }
1341   else
1342     {
1343       if (group_membership != NULL)
1344         group_membership[0] = 'N';
1345       if (group_ou != NULL)
1346         strcpy(group_ou, group_ou_neither);
1347     }
1348   return(0);
1349 }
1350
1351 int get_group_info(int ac, char**av, void *ptr)
1352 {
1353   char **call_args;
1354
1355   call_args = ptr;
1356
1357   if (!atoi(av[L_ACTIVE]))
1358     return(0);
1359   if (ptr == NULL)
1360     {
1361       get_group_membership(GroupType, NULL, NULL, av);
1362     }
1363   else
1364     {
1365     call_args[5] = av[L_NAME];
1366     get_group_membership(call_args[4], call_args[3], NULL, av);
1367     }
1368
1369   return(0);
1370 }
1371
1372 int group_rename(int ac, char **av, void *ptr)
1373 {
1374   LDAPMod   *mods[20];
1375   char      old_dn[512];
1376   char      new_dn[512];
1377   char      new_dn_path[512];
1378   char      group_ou[256];
1379   char      sam_name[256];
1380   char      group_membership[2];
1381   char      filter_exp[4096];
1382   char      *attr_array[3];
1383   char      *name_v[] = {NULL, NULL};
1384   char      *samAccountName_v[] = {NULL, NULL};
1385   int       n;
1386   int       i;
1387   int       rc;
1388   int       security_flag;
1389   LK_ENTRY  *group_base;
1390   int       group_count;
1391   char      **call_args;
1392   char      *maillist_flag = NULL;
1393   char      *group_flag = NULL;
1394
1395   call_args = ptr;
1396
1397   if (!check_string(call_args[2]))
1398     {
1399       callback_rc = LDAP_NO_SUCH_OBJECT;
1400       return(0);
1401     }
1402   if (!check_string(av[L_NAME]))
1403     {
1404       critical_alert("AD incremental - list rename",
1405                       "invalid LDAP list name %s",
1406                       av[L_NAME]);
1407       return(0);
1408     }
1409
1410   memset(group_ou, 0, sizeof(group_ou));
1411   memset(group_membership, 0, sizeof(group_membership));
1412   security_flag = 0;
1413
1414   maillist_flag = av[L_MAILLIST];
1415   group_flag = av[L_GROUP];
1416   av[L_MAILLIST] = call_args[3];
1417   av[L_GROUP] = call_args[4];
1418   get_group_membership(group_membership, NULL, NULL, av);
1419   av[L_MAILLIST] = maillist_flag;
1420   av[L_GROUP] = group_flag;
1421
1422   sprintf(filter_exp, "(sAMAccountName=%s_zZx%c)", call_args[2], group_membership[0]);
1423   attr_array[0] = "distinguishedName";
1424   attr_array[1] = NULL;
1425   if ((rc = linklist_build((LDAP *)call_args[0], call_args[1], filter_exp, attr_array, 
1426                            &group_base, &group_count)) != 0)
1427     {
1428       critical_alert("AD incremental - list rename",
1429                       "LDAP server unable to get list %s dn : %s",
1430                       call_args[2], ldap_err2string(rc));
1431       return(0);
1432     }
1433   if (group_count != 1)
1434     {
1435       critical_alert("AD incremental - list rename",
1436                       "LDAP server unable to find list %s in AD.",
1437                       call_args[2]);
1438       callback_rc = LDAP_NO_SUCH_OBJECT;
1439       return(0);
1440     }
1441   strcpy(old_dn, group_base->value);
1442   linklist_free(group_base);
1443   group_base = NULL;
1444   group_count = 0;
1445
1446   get_group_membership(group_membership, group_ou, &security_flag, av);
1447   sprintf(sam_name, "%s_zZx%c", av[L_NAME], group_membership[0]);
1448   sprintf(new_dn_path, "%s,%s", group_ou, call_args[1]);
1449   sprintf(new_dn, "cn=%s", av[L_NAME]);
1450   if ((rc = ldap_rename_s((LDAP *)call_args[0], old_dn, new_dn, new_dn_path,
1451                           TRUE, NULL, NULL)) != LDAP_SUCCESS)
1452     {
1453       critical_alert("AD incremental - list rename",
1454                      "Couldn't rename list from %s to %s : %s",
1455                      call_args[2], av[L_NAME], ldap_err2string(rc));
1456       return(0);
1457     }
1458
1459   name_v[0] = av[L_NAME];
1460   samAccountName_v[0] = sam_name;
1461   n = 0;
1462   ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
1463   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_REPLACE);
1464   mods[n] = NULL;
1465   sprintf(new_dn, "cn=%s,%s,%s", av[L_NAME], group_ou, call_args[1]);
1466   if ((rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods)) != LDAP_SUCCESS)
1467     {
1468        critical_alert("AD incremental - list rename", 
1469                       "After renaming, couldn't modify list data for %s : %s",
1470                        av[L_NAME], ldap_err2string(rc));
1471     }
1472   for (i = 0; i < n; i++)
1473     free(mods[i]);
1474   return(0);
1475 }
1476
1477 int group_create(int ac, char **av, void *ptr)
1478 {
1479   LDAPMod *mods[20];
1480   char new_dn[256];
1481   char group_ou[256];
1482   char new_group_name[256];
1483   char sam_group_name[256];
1484   char cn_group_name[256];
1485   char *cn_v[] = {NULL, NULL};
1486   char *objectClass_v[] = {"top", "group", NULL};
1487   char info[256];
1488   char *samAccountName_v[] = {NULL, NULL};
1489   char *managedBy_v[] = {NULL, NULL};
1490   char *altSecurityIdentities_v[] = {NULL, NULL};
1491   char *name_v[] = {NULL, NULL};
1492   char *desc_v[] = {NULL, NULL};
1493   char *info_v[] = {NULL, NULL};
1494   char *groupTypeControl_v[] = {NULL, NULL};
1495   char groupTypeControlStr[80];
1496   char group_membership[1];
1497   int  i;
1498   int  security_flag;
1499   u_int groupTypeControl = ADS_GROUP_TYPE_GLOBAL_GROUP;
1500   int  n;
1501   int  rc;
1502   int  sid_count;
1503   char filter_exp[256];
1504   char *attr_array[3];
1505   char **call_args;
1506
1507   call_args = ptr;
1508
1509   if (!atoi(av[L_ACTIVE]))
1510     return(0);
1511   if (!check_string(av[L_NAME]))
1512     {
1513       critical_alert("AD incremental - list create",
1514                       "invalid LDAP list name %s",
1515                       av[L_NAME]);
1516       return(0);
1517     }
1518   memset(group_ou, 0, sizeof(group_ou));
1519   memset(group_membership, 0, sizeof(group_membership));
1520   security_flag = 0;
1521   get_group_membership(group_membership, group_ou, &security_flag, av);
1522   call_args[3] = strdup(group_ou);
1523   call_args[4] = strdup(group_membership);
1524   call_args[5] = strdup(av[L_NAME]);
1525
1526   if (security_flag)
1527     groupTypeControl |= ADS_GROUP_TYPE_SECURITY_ENABLED;
1528   sprintf(groupTypeControlStr, "%ld", groupTypeControl);
1529   groupTypeControl_v[0] = groupTypeControlStr;
1530
1531   strcpy(new_group_name, av[L_NAME]);
1532   strcpy(sam_group_name, av[L_NAME]);
1533   strcpy(cn_group_name, av[L_NAME]);
1534   sprintf(&sam_group_name[strlen(sam_group_name)], 
1535           "_zZx%c", group_membership[0]);
1536
1537   samAccountName_v[0] = sam_group_name;
1538   name_v[0] = new_group_name;
1539   cn_v[0] = new_group_name;
1540
1541   sprintf(new_dn, "cn=%s,%s,%s", new_group_name, group_ou, call_args[1]);
1542   n = 0;
1543   ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
1544   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
1545   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
1546   ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
1547   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
1548   if (strlen(av[L_DESC]) != 0)
1549     {
1550       desc_v[0] = av[L_DESC];
1551       ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
1552     }
1553   ADD_ATTR("groupType", groupTypeControl_v, LDAP_MOD_ADD);
1554   if (strlen(av[L_ACE_NAME]) != 0)
1555     {
1556       sprintf(info, "The Administrator of this list is the LIST: %s", av[L_ACE_NAME]);
1557       info_v[0] = info;
1558       ADD_ATTR("info", info_v, LDAP_MOD_ADD);
1559     }
1560   mods[n] = NULL;
1561
1562   rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
1563
1564   for (i = 0; i < n; i++)
1565     free(mods[i]);
1566   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
1567     {
1568       critical_alert("AD incremental - list rename",
1569                       "Unable to create list %s in AD : %s",
1570                       av[L_NAME], ldap_err2string(rc));
1571       return(0);
1572     }
1573   sprintf(filter_exp, "(sAMAccountName=%s)", sam_group_name);
1574   attr_array[0] = "objectSid";
1575   attr_array[1] = NULL;
1576   sid_count = 0;
1577   if ((rc = linklist_build((LDAP *)call_args[0], call_args[1], filter_exp, attr_array, 
1578                            sid_ptr, &sid_count)) == LDAP_SUCCESS)
1579     {
1580       if (sid_count == 1)
1581         {
1582           (*sid_ptr)->member = strdup(av[L_NAME]);
1583           (*sid_ptr)->type = (char *)GROUPS;
1584           sid_ptr = &(*sid_ptr)->next;
1585         }
1586     }
1587   return(0);
1588 }
1589
1590 int group_delete(int ac, char **av, void *ptr)
1591 {
1592   LK_ENTRY  *group_base;
1593   char      **call_args;
1594   char      *attr_array[3];
1595   char      filter_exp[1024];
1596   char      group_membership[1];
1597   char      group_ou[256];
1598   char      sam_group_name[256];
1599   int       security_flag;
1600   int       group_count;
1601   int       rc;
1602
1603   call_args = ptr;
1604
1605   if (!check_string(av[L_NAME]))
1606     {
1607       critical_alert("AD incremental - list delete",
1608                       "invalid LDAP list name %s",
1609                       av[L_NAME]);
1610       return(0);
1611     }
1612   memset(group_ou, 0, sizeof(group_ou));
1613   memset(group_membership, 0, sizeof(group_membership));
1614   security_flag = 0;
1615   get_group_membership(group_membership, group_ou, &security_flag, av);
1616
1617   group_count = 0;
1618   group_base = NULL;
1619   attr_array[0] = "distinguishedName";
1620   attr_array[1] = NULL;
1621   strcpy(sam_group_name, av[L_NAME]);
1622   sprintf(&sam_group_name[strlen(sam_group_name)], "_zZx%c", 
1623           group_membership[0]);
1624   sprintf(filter_exp, "(sAMAccountName=%s)", sam_group_name);
1625   if ((rc = linklist_build((LDAP *)call_args[0], call_args[1], filter_exp, 
1626                            attr_array, &group_base, &group_count)) != 0)
1627     goto cleanup;
1628   if (group_count == 1)
1629     {
1630       if ((rc = ldap_delete_s((LDAP *)call_args[0], group_base->value)) != LDAP_SUCCESS)
1631         {
1632           critical_alert("AD incremental - list delete",
1633                          "Couldn't delete group %s : %s",
1634                          av[L_NAME], ldap_err2string(rc));
1635         }
1636     }
1637   else
1638     {
1639       critical_alert("AD incremental - list delete",
1640                       "Unable to find list %s in AD.",
1641                       av[L_NAME]);
1642     }
1643 cleanup:
1644   linklist_free(group_base);
1645   return(0);
1646 }
1647
1648 int group_ad_delete(LDAP *ldap_handle, char *dn_path, char *group_name)
1649 {
1650   LK_ENTRY  *group_base;
1651   char      *attr_array[3];
1652   char      filter_exp[1024];
1653   char      sam_group_name[256];
1654   char      temp[512];
1655   int       group_count;
1656   int       rc;
1657
1658   if (!check_string(group_name))
1659     {
1660       critical_alert("AD incremental - list AD delete",
1661                       "invalid LDAP list name %s",
1662                       group_name);
1663       return(0);
1664     }
1665   rc = 1;
1666   group_count = 0;
1667   group_base = NULL;
1668   attr_array[0] = "distinguishedName";
1669   attr_array[1] = NULL;
1670   strcpy(sam_group_name, group_name);
1671   sprintf(temp, "%s,%s", group_ou_root, dn_path);
1672   sprintf(filter_exp, "(sAMAccountName=%s_zZx*)", sam_group_name);
1673   if (linklist_build(ldap_handle, temp, filter_exp, attr_array, 
1674                            &group_base, &group_count) != 0)
1675     goto cleanup;
1676   if (group_count == 1)
1677     {
1678       if ((rc = ldap_delete_s(ldap_handle, group_base->value)) != LDAP_SUCCESS)
1679         {
1680           critical_alert("AD incremental - list AD delete",
1681                           "Unable to delete list %s from AD : %s",
1682                           group_name, ldap_err2string(rc));
1683           return(0);
1684         }
1685     }
1686   else
1687     {
1688       critical_alert("AD incremental - list AD delete",
1689                      "Unable to find list %s in AD.",
1690                       group_name);
1691     }
1692 cleanup:
1693   linklist_free(group_base);
1694   return(0);
1695 }
1696
1697 int group_list_build(int ac, char **av, void *ptr)
1698 {
1699   LK_ENTRY    *linklist;
1700   char        **call_args;
1701
1702   call_args = ptr;
1703
1704   if (!atoi(av[L_ACTIVE]))
1705     return(0);
1706   if (!check_string(av[L_NAME]))
1707     return(0);
1708   linklist = calloc(1, sizeof(LK_ENTRY));
1709   if (!linklist)
1710     {
1711       critical_alert("AD incremental", "Out of memory");
1712       exit(1);
1713     }
1714   memset(linklist, '\0', sizeof(LK_ENTRY));
1715   linklist->op = 1;
1716   linklist->dn = NULL;
1717   linklist->list = calloc(1, strlen(av[L_NAME]) + 1);
1718   strcpy(linklist->list, av[L_NAME]);
1719   linklist->type = calloc(1, strlen("USER") + 1);
1720   strcpy(linklist->type, "USER");
1721   linklist->member = calloc(1, strlen(call_args[0]) + 1);
1722   strcpy(linklist->member, call_args[0]);
1723   linklist->next = member_base;
1724   member_base = linklist;
1725   return(0);
1726 }
1727
1728 int member_list_build(int ac, char **av, void *ptr)
1729 {
1730   LK_ENTRY  *linklist;
1731   char      temp[1024];
1732   char      **call_args;
1733
1734   call_args = ptr;
1735
1736   strcpy(temp, av[ACE_NAME]);
1737   if (!check_string(temp))
1738     return(0);
1739   if (!strcmp(av[ACE_TYPE], "USER"))
1740     {
1741       if (!((int)call_args[6] & MOIRA_USERS))
1742         return(0);
1743     }
1744   else if (!strcmp(av[ACE_TYPE], "STRING"))
1745     {
1746       if (!((int)call_args[6] & MOIRA_STRINGS))
1747         return(0);
1748       if (contact_create((LDAP *)call_args[0], call_args[1], temp, contact_ou))
1749         return(0);
1750     }
1751   else if (!strcmp(av[ACE_TYPE], "LIST"))
1752     {
1753       if (!((int)call_args[6] & MOIRA_LISTS))
1754         return(0);
1755     }
1756   else if (!strcmp(av[ACE_TYPE], "KERBEROS"))
1757     {
1758       if (!((int)call_args[6] & MOIRA_KERBEROS))
1759         return(0);
1760       if (contact_create((LDAP *)call_args[0], call_args[1], temp, kerberos_ou))
1761         return(0);
1762     }
1763   else
1764     return(0);
1765
1766   linklist = member_base;
1767   while (linklist)
1768     {
1769     if (!strcasecmp(temp, linklist->member))
1770       return(0);
1771     linklist = linklist->next;
1772     }
1773   linklist = calloc(1, sizeof(LK_ENTRY));
1774   linklist->op = 1;
1775   linklist->dn = NULL;
1776   linklist->list = calloc(1, strlen(call_args[2]) + 1);
1777   strcpy(linklist->list, call_args[2]);
1778   linklist->type = calloc(1, strlen(av[ACE_TYPE]) + 1);
1779   strcpy(linklist->type, av[ACE_TYPE]);
1780   linklist->member = calloc(1, strlen(temp) + 1);
1781   strcpy(linklist->member, temp);
1782   linklist->next = member_base;
1783   member_base = linklist;
1784   return(0);
1785 }
1786
1787 int list_list_build(int ac, char **av, void *ptr)
1788 {
1789   LK_ENTRY  *linklist;
1790   char      temp[1024];
1791   char      **call_args;
1792
1793   call_args = ptr;
1794
1795   strcpy(temp, av[L_NAME]);
1796   if (!check_string(temp))
1797     return(0);
1798
1799   linklist = member_base;
1800   while (linklist)
1801     {
1802     if (!strcasecmp(temp, linklist->member))
1803       return(0);
1804     linklist = linklist->next;
1805     }
1806   linklist = calloc(1, sizeof(LK_ENTRY));
1807   linklist->op = 1;
1808   linklist->dn = NULL;
1809   linklist->list = calloc(1, strlen(call_args[2]) + 1);
1810   strcpy(linklist->list, call_args[2]);
1811   linklist->type = calloc(1, strlen("LIST") + 1);
1812   strcpy(linklist->type, "LIST");
1813   linklist->member = calloc(1, strlen(temp) + 1);
1814   strcpy(linklist->member, temp);
1815   linklist->next = member_base;
1816   member_base = linklist;
1817   return(0);
1818 }
1819
1820 int member_remove(LDAP *ldap_handle, char *dn_path, char *group_name, 
1821                   char *group_ou, char *group_membership, char *group_gid)
1822 {
1823   char        distinguished_name[1024];
1824   char        **modvalues;
1825   char        filter_exp[4096];
1826   char        *attr_array[3];
1827   char        temp[256];
1828   int         group_count;
1829   int         i;
1830   int         n;
1831   LDAPMod     *mods[20];
1832   LK_ENTRY    *group_base;
1833   ULONG       rc;
1834
1835   if (!check_string(group_name))
1836     return(0);
1837   strcpy(temp, group_name);
1838   sprintf(filter_exp, "(sAMAccountName=%s_zZx%c)", group_gid, group_membership[0]);
1839   attr_array[0] = "distinguishedName";
1840   attr_array[1] = NULL;
1841   if ((rc = linklist_build(ldap_handle, dn_path, filter_exp, attr_array, 
1842                            &group_base, &group_count)) != 0)
1843     {
1844       critical_alert("AD incremental - member remove",
1845                       "LDAP server unable to get list %s info : %s",
1846                       group_name, ldap_err2string(rc));
1847       goto cleanup;
1848     }
1849   if (group_count != 1)
1850     {
1851       critical_alert("AD incremental - member remove",
1852                       "LDAP server unable to find list %s in AD.",
1853                       group_name);
1854       goto cleanup;
1855     }
1856   strcpy(distinguished_name, group_base->value);
1857   linklist_free(group_base);
1858   group_base = NULL;
1859   group_count = 0;
1860   attr_array[0] = "member";
1861   attr_array[1] = NULL;
1862   if ((rc = linklist_build(ldap_handle, distinguished_name, filter_exp, attr_array, 
1863                            &group_base, &group_count)) != 0)
1864     {
1865       critical_alert("AD incremental - member remove",
1866                       "LDAP server unable to get list %s info : %s",
1867                       group_name, ldap_err2string(rc));
1868       goto cleanup;
1869     }
1870
1871   modvalues = NULL;
1872   if (group_count != 0)
1873     {
1874       if ((rc = construct_newvalues(group_base, group_count, NULL, NULL,
1875                                     &modvalues, REPLACE)) == 1)
1876           goto cleanup;
1877       n = 0;
1878       ADD_ATTR("member", modvalues, LDAP_MOD_DELETE);
1879       mods[n] = NULL;
1880       rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
1881       for (i = 0; i < n; i++)
1882         free(mods[i]);
1883       if (rc != LDAP_SUCCESS)
1884         {
1885           critical_alert("AD incremental - member remove",
1886                           "LDAP server unable to modify list %s members : %s",
1887                           group_name, ldap_err2string(rc));
1888           goto cleanup;
1889         }
1890       linklist_free(group_base);
1891       group_count = 0;
1892       group_base = NULL;
1893     }
1894
1895 cleanup:
1896   free_values(modvalues);
1897   linklist_free(group_base);
1898   return(rc);
1899 }
1900
1901 #define USER_COUNT  5
1902
1903 int member_list_process(LDAP *ldap_handle, char *dn_path, char *group_name, 
1904                         char *group_ou, char *group_membership, char *group_gid,
1905                         int operation)
1906 {
1907   char        distinguished_name[1024];
1908   char        **modvalues;
1909   char        filter_exp[4096];
1910   char        *attr_array[3];
1911   char        temp[256];
1912   char        group_member[256];
1913   char        *args[2];
1914   int         group_count;
1915   int         new_list_count;
1916   int         i;
1917   int         j;
1918   int         k;
1919   int         n;
1920   int         filter_count;
1921   LDAPMod     *mods[20];
1922   LK_ENTRY    *group_base;
1923   LK_ENTRY    *new_list;
1924   LK_ENTRY    *sPtr;
1925   LK_ENTRY    *pPtr;
1926   ULONG       rc;
1927
1928   rc = 0;
1929   group_base = NULL;
1930   group_count = 0;
1931   modvalues = NULL;
1932
1933   pPtr = member_base;
1934   while (pPtr)
1935     {
1936     ++group_count;
1937     pPtr = pPtr->next;
1938     }
1939   j = group_count/USER_COUNT;
1940   ++j;
1941
1942   if (!check_string(group_name))
1943     return(0);
1944   strcpy(temp, group_name);
1945   sprintf(filter_exp, "(sAMAccountName=%s_zZx%c)", group_gid, group_membership[0]);
1946   attr_array[0] = "distinguishedName";
1947   attr_array[1] = NULL;
1948   if ((rc = linklist_build(ldap_handle, dn_path, filter_exp, attr_array, 
1949                            &group_base, &group_count)) != 0)
1950     {
1951       critical_alert("AD incremental - member list process",
1952                       "LDAP server unable to get list %s info : %s",
1953                       group_name, ldap_err2string(rc));
1954       goto cleanup;
1955     }
1956   if (group_count != 1)
1957     {
1958       critical_alert("AD incremental - member list process",
1959                       "LDAP server unable to find list %s in AD.",
1960                       group_name);
1961       goto cleanup;
1962     }
1963   strcpy(distinguished_name, group_base->value);
1964   linklist_free(group_base);
1965   group_base = NULL;
1966   group_count = 0;
1967
1968   pPtr = member_base;
1969   for (i = 0; i < j; i++)
1970     {
1971       if (pPtr == NULL)
1972         break;
1973       memset(filter_exp, 0, sizeof(filter_exp));
1974       strcpy(filter_exp, "(|");
1975       filter_count = 0;
1976       for (k = 0; k < USER_COUNT; k++)
1977         {
1978           strcpy(group_member, pPtr->member);
1979           if (!check_string(group_member))
1980             {
1981               pPtr = pPtr->next;
1982               if (pPtr == NULL)
1983                 break;
1984               continue;
1985             }
1986           if (!strcmp(pPtr->type, "LIST"))
1987             {
1988               if (!(operation & MOIRA_LISTS))
1989                 continue;
1990               args[0] = pPtr->member;
1991               rc = mr_query("get_list_info", 1, args, get_group_info, NULL);
1992               sprintf(temp, "(sAMAccountName=%s_zZx%c)", group_member, GroupType[0]);
1993             }
1994           else if (!strcmp(pPtr->type, "USER"))
1995             {
1996               if (!(operation & MOIRA_USERS))
1997                 continue;
1998               sprintf(temp, "(distinguishedName=cn=%s,%s,%s)", group_member, user_ou, dn_path);
1999             }
2000           else if (!strcmp(pPtr->type, "STRING"))
2001             {
2002               if (!(operation & MOIRA_STRINGS))
2003                 continue;
2004               if ((group_membership[0] != 'B') && (group_membership[0] != 'D'))
2005                 continue;
2006               sprintf(temp, "(distinguishedName=cn=%s,%s,%s)", group_member, contact_ou, dn_path);
2007             }
2008           else
2009             {
2010               if (!(operation & MOIRA_KERBEROS))
2011                 continue;
2012               sprintf(temp, "(distinguishedName=cn=%s,%s,%s)", group_member, kerberos_ou, dn_path);
2013             }
2014           strcat(filter_exp, temp);
2015           ++filter_count;
2016           pPtr = pPtr->next;
2017           if (pPtr == NULL)
2018             break;
2019         }
2020       if (filter_count == 0)
2021         continue;
2022       strcat(filter_exp, ")");
2023       attr_array[0] = "distinguishedName";
2024       attr_array[1] = NULL;
2025       new_list = NULL;
2026       new_list_count = 0;
2027       if ((rc = linklist_build(ldap_handle, dn_path, filter_exp, attr_array, 
2028                                &new_list, &new_list_count)) != 0)
2029         {
2030           critical_alert("AD incremental - member list process",
2031                          "LDAP server unable to get list %s members from AD : %s",
2032                          group_name, ldap_err2string(rc));
2033           goto cleanup;
2034         }
2035       group_count += new_list_count;
2036       if (group_base == NULL)
2037         group_base = new_list;
2038       else
2039         {
2040           sPtr = group_base;
2041           while (sPtr)
2042             {
2043               if (sPtr->next != NULL)
2044                 {
2045                   sPtr = sPtr->next;
2046                   continue;
2047                 }
2048               sPtr->next = new_list;
2049               break;
2050             }
2051         }
2052     }
2053
2054   modvalues = NULL;
2055   if (group_count != 0)
2056     {
2057       if ((rc = construct_newvalues(group_base, group_count, NULL, NULL,
2058                                     &modvalues, REPLACE)) == 1)
2059           goto cleanup;
2060       n = 0;
2061       ADD_ATTR("member", modvalues, LDAP_MOD_ADD);
2062       mods[n] = NULL;
2063       if ((rc = ldap_modify_s(ldap_handle, distinguished_name, mods)) 
2064           != LDAP_SUCCESS)
2065         {
2066           mods[0]->mod_op = LDAP_MOD_REPLACE;
2067           rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
2068         }
2069       if (rc == LDAP_ALREADY_EXISTS)
2070         rc = LDAP_SUCCESS;
2071       for (i = 0; i < n; i++)
2072         free(mods[i]);
2073       linklist_free(group_base);
2074       group_count = 0;
2075       group_base = NULL;
2076       if (rc != LDAP_SUCCESS)
2077         {
2078           critical_alert("AD incremental - member list process",
2079                          "LDAP server unable to modify list %s members in AD : %s",
2080                          group_name, ldap_err2string(rc));
2081           goto cleanup;
2082         }
2083     }
2084
2085 cleanup:
2086   free_values(modvalues);
2087   linklist_free(group_base);
2088   return(0);
2089 }
2090
2091 int contact_create(LDAP *ld, char *bind_path, char *user, char *group_ou)
2092 {
2093   LDAPMod *mods[20];
2094   char new_dn[256];
2095   char cn_user_name[256];
2096   char contact_name[256];
2097   char *email_v[] = {NULL, NULL};
2098   char *cn_v[] = {NULL, NULL};
2099   char *contact_v[] = {NULL, NULL};
2100   char *objectClass_v[] = {"top", "person", 
2101                            "organizationalPerson", 
2102                            "contact", NULL};
2103   char *name_v[] = {NULL, NULL};
2104   char *desc_v[] = {NULL, NULL};
2105   int  n;
2106   int  rc;
2107   int  i;
2108
2109   if (!check_string(user))
2110     {
2111       critical_alert("AD incremental - contact create",
2112                       "invalid LDAP name %s",
2113                       user);
2114       return(1);
2115     }
2116   strcpy(contact_name, user);
2117   sprintf(cn_user_name,"CN=%s,%s,%s", contact_name, group_ou, bind_path);
2118   cn_v[0] = cn_user_name;
2119   contact_v[0] = contact_name;
2120   name_v[0] = user;
2121   desc_v[0] = "Auto account created by Moira";
2122   email_v[0] = user;
2123
2124   strcpy(new_dn, cn_user_name);
2125   n = 0;
2126   ADD_ATTR("cn", contact_v, LDAP_MOD_ADD);
2127   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2128   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2129   ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2130   ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2131   if (!strcmp(group_ou, contact_ou))
2132     {
2133       ADD_ATTR("mail", email_v, LDAP_MOD_ADD);
2134     }
2135   mods[n] = NULL;
2136
2137   rc = ldap_add_ext_s(ld, new_dn, mods, NULL, NULL);
2138   for (i = 0; i < n; i++)
2139     free(mods[i]);
2140   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2141     {
2142       n = 0;
2143       ADD_ATTR("cn", contact_v, LDAP_MOD_ADD);
2144       ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2145       ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2146       ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2147       ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2148       mods[n] = NULL;
2149       rc = ldap_add_ext_s(ld, new_dn, mods, NULL, NULL);
2150       for (i = 0; i < n; i++)
2151         free(mods[i]);
2152     }
2153   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2154     {
2155       critical_alert("AD incremental - contact create", 
2156                      "could not create contact %s : %s",
2157                      user, ldap_err2string(rc));
2158       return(1);
2159     }
2160   return(0);
2161 }
2162
2163 int user_update(int ac, char **av, void *ptr)
2164 {
2165   LDAPMod   *mods[20];
2166   LK_ENTRY  *group_base;
2167   int  group_count;
2168   char distinguished_name[256];
2169   char user_name[256];
2170   char *uid_v[] = {NULL, NULL};
2171   char *mitid_v[] = {NULL, NULL};
2172   char *homedir_v[] = {NULL, NULL};
2173   char *winProfile_v[] = {NULL, NULL};
2174   char *drives_v[] = {NULL, NULL};
2175   int  n;
2176   int  rc;
2177   int  i;
2178   char **call_args;
2179   char filter_exp[256];
2180   char *attr_array[3];
2181   char **hp;
2182   char path[256];
2183   char winPath[256];
2184   char winProfile[256];
2185
2186   call_args = ptr;
2187
2188   if (!check_string(av[U_NAME]))
2189     {
2190       critical_alert("AD incremental - user update",
2191                       "invalid LDAP user name %s",
2192                       av[U_NAME]);
2193       return(0);
2194     }
2195
2196   strcpy(user_name, av[U_NAME]);
2197   group_count = 0;
2198   group_base = NULL;
2199   sprintf(filter_exp, "(sAMAccountName=%s)", av[U_NAME]);
2200   attr_array[0] = "cn";
2201   attr_array[1] = NULL;
2202   if ((rc = linklist_build((LDAP *)call_args[0], call_args[1], filter_exp, attr_array, 
2203                            &group_base, &group_count)) != 0)
2204     {
2205       critical_alert("AD incremental - user update",
2206                      "LDAP server couldn't process user %s : %s",
2207                       user_name, ldap_err2string(rc));
2208       goto cleanup;
2209     }
2210
2211   if (group_count != 1)
2212     {
2213       critical_alert("AD incremental - user update",
2214                      "LDAP server unable to find user %s in AD.",
2215                       user_name);
2216       callback_rc = LDAP_NO_SUCH_OBJECT;
2217       goto cleanup;
2218     }
2219   strcpy(distinguished_name, group_base->dn);
2220
2221   n = 0;
2222   if (strlen(av[U_UID]) != 0)
2223     {
2224       uid_v[0] = av[U_UID];
2225       ADD_ATTR("uid", uid_v, LDAP_MOD_REPLACE);
2226       ADD_ATTR("uidNumber", uid_v, LDAP_MOD_REPLACE);
2227     }
2228   if (strlen(av[U_MITID]) != 0)
2229     {
2230       mitid_v[0] = av[U_MITID];
2231       ADD_ATTR("employeeID", mitid_v, LDAP_MOD_REPLACE);
2232     }
2233   if ((hp = hes_resolve(user_name, "filsys")) != NULL)
2234     {
2235       memset(path, 0, sizeof(path));
2236       memset(winPath, 0, sizeof(winPath));
2237       sscanf(hp[0], "%*s %s", path);
2238       if (strlen(path) && strnicmp(path, AFS, strlen(AFS)) == 0)
2239         {
2240           AfsToWinAfs(path, winPath);
2241           homedir_v[0] = winPath;
2242           ADD_ATTR("homeDirectory", homedir_v, LDAP_MOD_REPLACE);
2243           strcpy(winProfile, winPath);
2244           strcat(winProfile, "\\.winprofile");
2245           winProfile_v[0] = winProfile;
2246           ADD_ATTR("profilePath", winProfile_v, LDAP_MOD_REPLACE);
2247           drives_v[0] = "H:";
2248           ADD_ATTR("homeDrive", drives_v, LDAP_MOD_REPLACE);
2249         }
2250     }
2251   mods[n] = NULL;
2252   if (n != 0)
2253     {
2254       if ((rc = ldap_modify_s((LDAP *)call_args[0], distinguished_name, mods)) != LDAP_SUCCESS)
2255         {
2256            critical_alert("AD incremental - user update", 
2257                           "Couldn't modify user data for %s : %s",
2258                            user_name, ldap_err2string(rc));
2259         }
2260       for (i = 0; i < n; i++)
2261         free(mods[i]);
2262     }
2263   if (hp != NULL)
2264     {
2265       i = 0;
2266       while (hp[i])
2267         {
2268           free(hp[i]);
2269           i++;
2270         }
2271     }
2272
2273 cleanup:
2274   linklist_free(group_base);
2275   return(0);
2276 }
2277
2278 int user_rename(int ac, char **av, void *ptr)
2279 {
2280   LDAPMod *mods[20];
2281   char new_dn[256];
2282   char old_dn[256];
2283   char user_name[256];
2284   char upn[256];
2285   char temp[128];
2286   char *userPrincipalName_v[] = {NULL, NULL};
2287   char *altSecurityIdentities_v[] = {NULL, NULL};
2288   char *name_v[] = {NULL, NULL};
2289   char *samAccountName_v[] = {NULL, NULL};
2290   char *uid_v[] = {NULL, NULL};
2291   char *mitid_v[] = {NULL, NULL};
2292   int  n;
2293   int  rc;
2294   int  i;
2295   char **call_args;
2296
2297   call_args = ptr;
2298
2299   if ((atoi(av[U_STATE]) != US_REGISTERED) && (atoi(av[U_STATE]) != US_NO_PASSWD) && 
2300       (atoi(av[U_STATE]) != US_ENROLL_NOT_ALLOWED))
2301     return(0);
2302   if (!strncmp(av[U_NAME], "#", 1))
2303     return(0);
2304   if (!check_string(call_args[3]))
2305     {
2306     callback_rc = LDAP_NO_SUCH_OBJECT;
2307     return(0);
2308     }
2309   if (!check_string(av[U_NAME]))
2310     {
2311       critical_alert("AD incremental - user rename",
2312                       "invalid LDAP user name %s",
2313                       av[U_NAME]);
2314       return(0);
2315     }
2316
2317   strcpy(user_name, av[U_NAME]);
2318   sprintf(old_dn, "cn=%s,%s,%s", call_args[3], user_ou, call_args[1]);
2319   sprintf(new_dn, "cn=%s", user_name);
2320
2321   if ((rc = ldap_rename_s((LDAP *)call_args[0], old_dn, new_dn, NULL, TRUE, 
2322                            NULL, NULL)) != LDAP_SUCCESS)
2323     {
2324       if (rc == LDAP_NO_SUCH_OBJECT)
2325         {
2326           callback_rc = LDAP_NO_SUCH_OBJECT;
2327           return(0);
2328         }
2329       critical_alert("AD incremental - user rename", 
2330                      "Couldn't rename user from %s to %s : %s",
2331                       call_args[3], user_name, ldap_err2string(rc));
2332       return(0);
2333     }
2334
2335   name_v[0] = user_name;
2336   sprintf(upn, "%s@%s", user_name, ldap_domain);
2337   userPrincipalName_v[0] = upn;
2338   sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
2339   altSecurityIdentities_v[0] = temp;
2340   samAccountName_v[0] = user_name;
2341
2342   n = 0;
2343   ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_REPLACE);
2344   ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_REPLACE);
2345   ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
2346   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_REPLACE);
2347   if (strlen(av[U_UID]) != 0)
2348     {
2349       uid_v[0] = av[U_UID];
2350       ADD_ATTR("uid", uid_v, LDAP_MOD_REPLACE);
2351       ADD_ATTR("uidNumber", uid_v, LDAP_MOD_REPLACE);
2352     }
2353   if (strlen(av[U_MITID]) != 0)
2354     {
2355       mitid_v[0] = av[U_MITID];
2356       ADD_ATTR("employeeID", mitid_v, LDAP_MOD_REPLACE);
2357     }
2358   mods[n] = NULL;
2359   sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, call_args[1]);
2360   if ((rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods)) != LDAP_SUCCESS)
2361     {
2362        critical_alert("AD incremental - user rename", 
2363                       "After renaming, couldn't modify user data for %s : %s",
2364                        user_name, ldap_err2string(rc));
2365     }
2366   for (i = 0; i < n; i++)
2367     free(mods[i]);
2368   return(0);
2369 }
2370
2371 int filesys_process(int ac, char **av, void *ptr)
2372 {
2373   char  distinguished_name[256];
2374   char  winPath[256];
2375   char  winProfile[256];
2376   char  fs_name[128];
2377   char  filter_exp[256];
2378   char  *attr_array[3];
2379   char  *homedir_v[] = {NULL, NULL};
2380   char  *winProfile_v[] = {NULL, NULL};
2381   char  *drives_v[] = {NULL, NULL};
2382   char  **call_args;
2383   int   group_count;
2384   int   n;
2385   int   rc;
2386   int   i;
2387   int   operation;
2388   LDAPMod   *mods[20];
2389   LK_ENTRY  *group_base;
2390
2391   call_args = ptr;
2392
2393   if (!check_string(av[FS_NAME]))
2394     {
2395       critical_alert("AD incremental - user filesys",
2396                       "invalid filesys name %s",
2397                       av[FS_NAME]);
2398       return(0);
2399     }
2400
2401
2402   if (strcmp(av[FS_TYPE], "AFS"))
2403     {
2404       critical_alert("AD incremental - user filesys",
2405                       "invalid filesys type %s",
2406                       av[FS_TYPE]);
2407       return(0);
2408     }
2409
2410   sleep(10);
2411   strcpy(fs_name, av[FS_NAME]);
2412   group_count = 0;
2413   group_base = NULL;
2414   sprintf(filter_exp, "(sAMAccountName=%s)", av[FS_NAME]);
2415   attr_array[0] = "cn";
2416   attr_array[1] = NULL;
2417   if ((rc = linklist_build((LDAP *)call_args[0], call_args[1], filter_exp, attr_array, 
2418                            &group_base, &group_count)) != 0)
2419     {
2420       critical_alert("AD incremental - user update",
2421                      "LDAP server couldn't process filesys %s : %s",
2422                       fs_name, ldap_err2string(rc));
2423       goto cleanup;
2424     }
2425
2426   if (group_count != 1)
2427     {
2428       critical_alert("AD incremental - user update",
2429                      "LDAP server unable to find user %s in AD.",
2430                       fs_name);
2431       callback_rc = LDAP_NO_SUCH_OBJECT;
2432       goto cleanup;
2433     }
2434   strcpy(distinguished_name, group_base->dn);
2435
2436   operation = LDAP_MOD_ADD;
2437   if ((int)call_args[3] == ADFS_DELETE)
2438     operation = LDAP_MOD_DELETE;
2439
2440   n = 0;
2441   if (operation == LDAP_MOD_ADD)
2442     {
2443       memset(winPath, 0, sizeof(winPath));
2444       AfsToWinAfs(av[FS_PACK], winPath);
2445       homedir_v[0] = winPath;
2446       drives_v[0] = "H:";
2447       memset(winProfile, 0, sizeof(winProfile));
2448       strcpy(winProfile, winPath);
2449       strcat(winProfile, "\\.winprofile");
2450       winProfile_v[0] = winProfile;
2451     }
2452   else
2453     {
2454       homedir_v[0] = NULL;
2455       drives_v[0] = NULL;
2456       winProfile_v[0] = NULL;
2457     }
2458   ADD_ATTR("profilePath", winProfile_v, operation);
2459   ADD_ATTR("homeDrive", drives_v, operation);
2460   ADD_ATTR("homeDirectory", homedir_v, operation);
2461   mods[n] = NULL;
2462
2463   for (i = 1; i < 6; i++)
2464     {
2465       if ((rc = ldap_modify_s((LDAP *)call_args[0], distinguished_name, mods)) == LDAP_SUCCESS)
2466         break;
2467       sleep(10);
2468     }
2469   if (rc != LDAP_SUCCESS)
2470     {
2471       critical_alert("AD incremental - filesys update", 
2472                      "Couldn't modify user data for filesys %s : %s",
2473                      fs_name, ldap_err2string(rc));
2474     }
2475   for (i = 0; i < n; i++)
2476     free(mods[i]);
2477
2478 cleanup:
2479   return(0);
2480 }
2481
2482 int user_create(int ac, char **av, void *ptr)
2483 {
2484   LDAPMod *mods[20];
2485   char new_dn[256];
2486   char user_name[256];
2487   char sam_name[256];
2488   char *cn_v[] = {NULL, NULL};
2489   char *objectClass_v[] = {"top", "person", 
2490                            "organizationalPerson", 
2491                            "user", NULL};
2492
2493   char *samAccountName_v[] = {NULL, NULL};
2494   char *altSecurityIdentities_v[] = {NULL, NULL};
2495   char *name_v[] = {NULL, NULL};
2496   char *desc_v[] = {NULL, NULL};
2497   char upn[256];
2498   char *userPrincipalName_v[] = {NULL, NULL};
2499   char *userAccountControl_v[] = {NULL, NULL};
2500   char *uid_v[] = {NULL, NULL};
2501   char *mitid_v[] = {NULL, NULL};
2502   char userAccountControlStr[80];
2503   char temp[128];
2504   u_int userAccountControl = UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD | UF_PASSWD_CANT_CHANGE;
2505   int  n;
2506   int  rc;
2507   int  i;
2508   int  sid_count;
2509   char filter_exp[256];
2510   char *attr_array[3];
2511   char **call_args;
2512
2513   call_args = ptr;
2514
2515   if ((atoi(av[U_STATE]) != US_REGISTERED) && (atoi(av[U_STATE]) != US_NO_PASSWD) && 
2516       (atoi(av[U_STATE]) != US_ENROLL_NOT_ALLOWED))
2517     return(0);
2518   if (!strncmp(av[U_NAME], "#", 1))
2519     return(0);
2520   if (!check_string(av[U_NAME]))
2521     {
2522       critical_alert("AD incremental - user create",
2523                       "invalid LDAP user name %s",
2524                       av[U_NAME]);
2525       return(0);
2526     }
2527
2528   strcpy(user_name, av[U_NAME]);
2529   sprintf(upn, "%s@%s", user_name, ldap_domain);
2530   sprintf(sam_name, "%s", av[U_NAME]);
2531   samAccountName_v[0] = sam_name;
2532   if (atoi(av[U_STATE]) == US_DELETED)
2533     userAccountControl |= UF_ACCOUNTDISABLE;
2534   sprintf(userAccountControlStr, "%ld", userAccountControl);
2535   userAccountControl_v[0] = userAccountControlStr;
2536   userPrincipalName_v[0] = upn;
2537
2538   cn_v[0] = user_name;
2539   name_v[0] = user_name;
2540   desc_v[0] = "Auto account created by Moira";
2541   sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
2542   altSecurityIdentities_v[0] = temp;    
2543   sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, call_args[1]);
2544
2545   n = 0;
2546   ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
2547   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2548   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
2549   ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_ADD);
2550   ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_ADD);
2551   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2552   ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2553   ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2554   ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_ADD);
2555   if (strlen(av[U_UID]) != 0)
2556     {
2557       uid_v[0] = av[U_UID];
2558       ADD_ATTR("uid", uid_v, LDAP_MOD_ADD);
2559       ADD_ATTR("uidNumber", uid_v, LDAP_MOD_ADD);
2560     }
2561   if (strlen(av[U_MITID]) != 0)
2562       mitid_v[0] = av[U_MITID];
2563   else
2564       mitid_v[0] = "none";
2565   ADD_ATTR("employeeID", mitid_v, LDAP_MOD_ADD);
2566   mods[n] = NULL;
2567
2568   rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
2569   for (i = 0; i < n; i++)
2570     free(mods[i]);
2571   if (rc == LDAP_ALREADY_EXISTS)
2572     {
2573       rc = user_change_status(ac, av, ptr);
2574       return(0);
2575     }
2576   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2577     {
2578        critical_alert("AD incremental - user create", 
2579                       "could not create user %s : %s",
2580                        user_name, ldap_err2string(rc));
2581        return(0);
2582     }
2583   if (rc == LDAP_SUCCESS)
2584     {
2585       if ((rc = set_password(sam_name, "", ldap_domain)) != 0)
2586         {
2587           critical_alert("AD incremental - user create", 
2588                          "Couldn't set password for user %s : %ld",
2589                          user_name, rc);
2590         }
2591     }
2592   sprintf(filter_exp, "(sAMAccountName=%s)", av[U_NAME]);
2593   attr_array[0] = "objectSid";
2594   attr_array[1] = NULL;
2595   sid_count = 0;
2596   if ((rc = linklist_build((LDAP *)call_args[0], call_args[1], filter_exp, attr_array, 
2597                            sid_ptr, &sid_count)) == LDAP_SUCCESS)
2598     {
2599       if (sid_count == 1)
2600         {
2601           (*sid_ptr)->member = strdup(av[U_NAME]);
2602           (*sid_ptr)->type = (char *)USERS;
2603           sid_ptr = &(*sid_ptr)->next;
2604         }
2605     }
2606   return(0);
2607 }
2608
2609 int user_change_status(int ac, char **av, void *ptr)
2610 {
2611   char      filter_exp[1024];
2612   char      *attr_array[3];
2613   char      temp[256];
2614   char      distinguished_name[1024];
2615   char      user_name[512];
2616   char      **modvalues;
2617   LDAPMod   *mods[20];
2618   LK_ENTRY  *group_base;
2619   int       group_count;
2620   int       rc;
2621   int       i;
2622   int       n;
2623   int       operation;
2624   ULONG     ulongValue;
2625   char **call_args;
2626
2627   call_args = ptr;
2628
2629   if (!check_string(av[U_NAME]))
2630     {
2631       critical_alert("AD incremental - user change status",
2632                       "invalid LDAP user name %s",
2633                       av[U_NAME]);
2634       return(0);
2635     }
2636   strcpy(user_name, av[U_NAME]);
2637   operation = (int)call_args[2];
2638   group_count = 0;
2639   group_base = NULL;
2640   sprintf(filter_exp, "(sAMAccountName=%s)", av[U_NAME]);
2641   attr_array[0] = "UserAccountControl";
2642   attr_array[1] = NULL;
2643   if ((rc = linklist_build((LDAP *)call_args[0], call_args[1], filter_exp, attr_array, 
2644                            &group_base, &group_count)) != 0)
2645     {
2646       critical_alert("AD incremental - user change status",
2647                      "LDAP server couldn't process user %s : %s",
2648                       user_name, ldap_err2string(rc));
2649       goto cleanup;
2650     }
2651
2652   if (group_count != 1)
2653     {
2654       critical_alert("AD incremental - user change status",
2655                      "LDAP server unable to find user %s in AD.",
2656                       user_name);
2657       goto cleanup;
2658     }
2659
2660   strcpy(distinguished_name, group_base->dn);
2661   ulongValue = atoi((*group_base).value);
2662   if (operation == MEMBER_DEACTIVATE)
2663     ulongValue |= UF_ACCOUNTDISABLE;
2664   else    
2665     ulongValue &= ~UF_ACCOUNTDISABLE;
2666   sprintf(temp, "%ld", ulongValue);
2667   if ((rc = construct_newvalues(group_base, group_count, (*group_base).value, 
2668                                 temp, &modvalues, REPLACE)) == 1)
2669       goto cleanup;
2670   linklist_free(group_base);
2671   group_base = NULL;
2672   group_count = 0;
2673   n = 0;
2674   ADD_ATTR("UserAccountControl", modvalues, LDAP_MOD_REPLACE);
2675   mods[n] = NULL;
2676   rc = ldap_modify_s((LDAP *)call_args[0], distinguished_name, mods);
2677   for (i = 0; i < n; i++)
2678     free(mods[i]);
2679   free_values(modvalues);
2680   if (rc != LDAP_SUCCESS)
2681     {
2682       critical_alert("AD incremental - user change status",
2683                      "LDAP server could not change status of user %s : %s",
2684                      user_name, ldap_err2string(rc));
2685     }
2686 cleanup:
2687   linklist_free(group_base);
2688   return(0);
2689 }
2690
2691 int user_delete(LDAP *ldap_handle, char *dn_path, char *u_name)
2692 {
2693   char      filter_exp[1024];
2694   char      *attr_array[3];
2695   char      distinguished_name[1024];
2696   char      user_name[512];
2697   LK_ENTRY  *group_base;
2698   int       group_count;
2699   int       rc;
2700
2701   if (!check_string(u_name))
2702     return(0);
2703   strcpy(user_name, u_name);
2704   group_count = 0;
2705   group_base = NULL;
2706   sprintf(filter_exp, "(sAMAccountName=%s)", user_name);
2707   attr_array[0] = "name";
2708   attr_array[1] = NULL;
2709   if ((rc = linklist_build(ldap_handle, dn_path, filter_exp, attr_array, 
2710                            &group_base, &group_count)) != 0)
2711     {
2712       critical_alert("AD incremental",
2713                      "LDAP server couldn't process user %s : %s",
2714                       user_name, ldap_err2string(rc));
2715       goto cleanup;
2716     }
2717
2718   if (group_count != 1)
2719     {
2720       critical_alert("AD incremental - user change status",
2721                      "LDAP server unable to find user %s in AD.",
2722                       user_name);
2723       goto cleanup;
2724     }
2725
2726   strcpy(distinguished_name, group_base->dn);
2727   if (rc = ldap_delete_s(ldap_handle, distinguished_name))
2728     {
2729       critical_alert("AD incremental",
2730                      "LDAP server couldn't process user %s : %s",
2731                       user_name, ldap_err2string(rc));
2732     }
2733
2734 cleanup:
2735   linklist_free(group_base);
2736   return(0);
2737 }
2738
2739 void linklist_free(LK_ENTRY *linklist_base)
2740 {
2741   LK_ENTRY *linklist_previous;
2742
2743   while (linklist_base != NULL)
2744     {
2745       if (linklist_base->dn != NULL)
2746         free(linklist_base->dn);
2747       if (linklist_base->attribute != NULL)
2748         free(linklist_base->attribute);
2749       if (linklist_base->value != NULL)
2750         free(linklist_base->value);
2751       if (linklist_base->member != NULL)
2752         free(linklist_base->member);
2753       if (linklist_base->type != NULL)
2754         free(linklist_base->type);
2755       if (linklist_base->list != NULL)
2756         free(linklist_base->list);
2757       linklist_previous = linklist_base;
2758       linklist_base = linklist_previous->next;
2759       free(linklist_previous);
2760     }
2761 }
2762
2763 void free_values(char **modvalues)
2764 {
2765   int i;
2766
2767   i = 0;
2768   if (modvalues != NULL)
2769     {
2770     while (modvalues[i] != NULL)
2771       {
2772         free(modvalues[i]);
2773         modvalues[i] = NULL;
2774         ++i;
2775       }
2776     free(modvalues);
2777   }
2778 }
2779
2780 int sid_update(LDAP *ldap_handle, char *dn_path)
2781 {
2782   LK_ENTRY      *ptr;
2783   int           rc;
2784   unsigned char temp[126];
2785   char          *av[3];
2786
2787   ptr = sid_base;
2788
2789   while (ptr != NULL)
2790     {
2791       memset(temp, 0, sizeof(temp));
2792       convert_b_to_a(temp, ptr->value, ptr->length);
2793       av[0] = ptr->member;
2794       av[1] = temp;
2795       if (ptr->type == (char *)GROUPS)
2796         {
2797           ptr->type = NULL;
2798           rc = mr_query("add_list_sid_by_name", 2, av, NULL, NULL);
2799         }
2800       else if (ptr->type == (char *)USERS)
2801         {
2802           ptr->type = NULL;
2803           rc = mr_query("add_user_sid_by_login", 2, av, NULL, NULL);
2804         }
2805       ptr = ptr->next;
2806     }
2807   return(0);
2808 }
2809
2810 void convert_b_to_a(char *string, UCHAR *binary, int length)
2811 {
2812   int   i;
2813   int   j;
2814   UCHAR tmp;
2815
2816   j = 0;
2817   for (i = 0; i < length; i++)
2818     {
2819       tmp = binary[i];
2820       string[j] = tmp;
2821       string[j] >>= 4;
2822       string[j] &= 0x0f;
2823       string[j] += 0x30;
2824       if (string[j] > '9')
2825         string[j] += 0x27;
2826       ++j;
2827       string[j] = tmp & 0x0f;
2828       string[j] += 0x30;
2829       if (string[j] > '9')
2830         string[j] += 0x27;
2831       j++;
2832     }
2833   string[j] = 0;
2834 }
2835
2836 static int illegalchars[] = {
2837   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
2838   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
2839   1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, /* SPACE - / */
2840   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 0 - ? */
2841   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
2842   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* P - _ */
2843   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
2844   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
2845   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2846   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2847   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2848   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2849   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2850   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2851   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2852   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2853 };
2854
2855 int check_string(char *s)
2856 {
2857   char  character;
2858
2859   for (; *s; s++)
2860     {
2861       character = *s;
2862       if (isupper(character))
2863         character = tolower(character);
2864       if (illegalchars[(unsigned) character])
2865         return 0;
2866     }
2867   return 1;
2868 }
2869
2870 int mr_connect_cl(char *server, char *client, int version, int auth)
2871 {
2872   int   status;
2873   char  *motd;
2874   char  temp[128];
2875
2876   status = mr_connect(server);
2877   if (status)
2878     {
2879       com_err(whoami, status, "while connecting to Moira");
2880       return status;
2881     }
2882
2883   status = mr_motd(&motd);
2884   if (status)
2885     {
2886       mr_disconnect();
2887       com_err(whoami, status, "while checking server status");
2888       return status;
2889     }
2890   if (motd)
2891     {
2892       sprintf(temp, "The Moira server is currently unavailable: %s", motd);
2893       com_err(whoami, status, temp);
2894       mr_disconnect();
2895       return status;
2896     }
2897
2898   status = mr_version(version);
2899   if (status)
2900     {
2901       if (status == MR_UNKNOWN_PROC)
2902         {
2903           if (version > 2)
2904             status = MR_VERSION_HIGH;
2905           else
2906             status = MR_SUCCESS;
2907         }
2908
2909       if (status == MR_VERSION_HIGH)
2910         {
2911           com_err(whoami, 0, "Warning: This client is running newer code than the server.");
2912                   com_err(whoami, 0, "Some operations may not work.");
2913         }
2914       else if (status && status != MR_VERSION_LOW)
2915         {
2916           com_err(whoami, status, "while setting query version number.");
2917           mr_disconnect();
2918           return status;
2919         }
2920     }
2921
2922   if (auth)
2923     {
2924       status = mr_auth(client);
2925       if (status)
2926         {
2927           com_err(whoami, status, "while authenticating to Moira.");
2928           mr_disconnect();
2929           return status;
2930         }
2931     }
2932
2933   return MR_SUCCESS;
2934 }
2935
2936 void expand_groups(LDAP *ldap_handle, char *dn_path, char *group_name)
2937 {
2938   LK_ENTRY  *group_base = NULL;
2939   LK_ENTRY  *ptr = NULL;
2940   char      *call_args[7];
2941   char      *av[2];
2942   int       rc;
2943   int       before_count;
2944   int       after_count;
2945
2946   av[0] = "RLIST";
2947   av[1] = group_name;
2948   call_args[0] = (char *)ldap_handle;
2949   call_args[1] = dn_path;
2950   call_args[2] = group_name;
2951   call_args[3] = NULL;
2952
2953   linklist_free(member_base);
2954   member_base = NULL;
2955   linklist_free(sid_base);
2956   sid_base = NULL;
2957   if (mr_query("get_lists_of_member", 2, av, list_list_build, call_args) == MR_NO_MATCH)
2958     return;
2959   if (member_base == NULL)
2960     return;
2961   while (1)
2962     {
2963       group_base = member_base;
2964       ptr = group_base;
2965       before_count = 0;
2966       while(ptr != NULL)
2967         {
2968           ++before_count;
2969           ptr = ptr->next;
2970         }
2971       ptr = group_base;
2972       while (ptr != NULL)
2973         {
2974           sleep(1);
2975           av[0] = "RLIST";
2976           av[1] = ptr->member;
2977           call_args[0] = (char *)ldap_handle;
2978           call_args[1] = dn_path;
2979           call_args[2] = ptr->member;
2980           call_args[3] = NULL;
2981           mr_query("get_lists_of_member", 2, av, list_list_build, call_args);
2982           ptr = ptr->next;
2983         }
2984       after_count = 0;
2985       ptr = group_base;
2986       while(ptr != NULL)
2987         {
2988           ++after_count;
2989           ptr = ptr->next;
2990         }
2991       if (before_count == after_count)
2992         break;
2993     }
2994
2995   group_base = member_base;
2996   ptr = group_base;
2997   while (ptr != NULL)
2998     {
2999       sleep(1);
3000       member_base = NULL;
3001       sid_base = NULL;
3002       sid_ptr = &sid_base;
3003       av[0] = ptr->member;
3004       av[1] = NULL;
3005       call_args[0] = (char *)ldap_handle;
3006       call_args[1] = dn_path;
3007       call_args[2] = ptr->member;
3008       call_args[3] = NULL;
3009       call_args[4] = NULL;
3010       call_args[5] = NULL;
3011       call_args[6] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
3012       if (rc = mr_query("get_list_info", 1, av, group_create, call_args))
3013         {
3014           linklist_free(member_base);
3015           linklist_free(sid_base);
3016           sid_base = NULL;
3017           member_base = NULL;
3018           ptr = ptr->next;
3019           continue;
3020         }
3021       if ((call_args[3] == NULL) || (call_args[4] == NULL) || (call_args[5] == NULL))
3022         {
3023           linklist_free(member_base);
3024           linklist_free(sid_base);
3025           sid_base = NULL;
3026           member_base = NULL;
3027           ptr = ptr->next;
3028           continue;
3029         }
3030       if (sid_base != NULL)
3031         {
3032           sid_update(ldap_handle, dn_path);
3033           linklist_free(sid_base);
3034           sid_base = NULL;
3035         }
3036       sleep(1);
3037       member_base = NULL;
3038       if (!(rc = mr_query("get_end_members_of_list", 1, av, member_list_build,
3039                           call_args)))
3040         {
3041           if (member_base == NULL)
3042             {
3043               member_remove(ldap_handle, dn_path, ptr->member,
3044                             call_args[3], call_args[4], call_args[5]);
3045             }
3046           else
3047             {
3048               rc = member_list_process(ldap_handle, dn_path, ptr->member,
3049                                        call_args[3], call_args[4], call_args[5],
3050                                        MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
3051             }
3052         }
3053       linklist_free(member_base);
3054       member_base = NULL;
3055       if (call_args[3] != NULL)
3056         free(call_args[3]);
3057       if (call_args[4] != NULL)
3058         free(call_args[4]);
3059       call_args[3] = NULL;
3060       call_args[4] = NULL;
3061       call_args[5] = NULL;
3062       call_args[6] = NULL;
3063       ptr = ptr->next;
3064     }
3065   linklist_free(group_base);
3066   group_base = NULL;
3067   return;
3068 }
3069
3070 void AfsToWinAfs(char* path, char* winPath)
3071 {
3072     char* pathPtr;
3073     char* winPathPtr;
3074     strcpy(winPath, WINAFS);
3075     pathPtr = path + strlen(AFS);
3076     winPathPtr = winPath + strlen(WINAFS);
3077
3078     while (*pathPtr)
3079     {
3080         if (*pathPtr == '/')
3081           *winPathPtr = '\\';
3082         else
3083           *winPathPtr = *pathPtr;
3084
3085         pathPtr++;
3086         winPathPtr++;
3087     }
3088 }
This page took 1.269635 seconds and 5 git commands to generate.