]> andersk Git - moira.git/blob - incremental/ldap/winad.c
Handle nfsgroup bit.
[moira.git] / incremental / ldap / winad.c
1 /* $Header$
2 /* ldap.incr arguments example
3  *
4  * arguments when moira creates the account - ignored by ldap.incr since the 
5  * account is unusable. users 0 11 #45198 45198 /bin/cmd cmd Last First Middle
6  * 0 950000001 2000 121049
7  *
8  * login, unix_uid, shell, winconsoleshell, last, 
9  * first, middle, status, mitid, type, moiraid
10  *
11  * arguments for creating or updating a user account 
12  * users 11 11 username 45206 /bin/cmd cmd Last First Middle 2 950000001 STAFF
13  * 121058  PathToHomeDir PathToProfileDir username 45206 /bin/cmd cmd Last
14  * First Middle 1 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
15  * users 11 11 #45206 45206 /bin/cmd cmd Last First Middle 0 950000001 STAFF
16  * 121058  PathToHomeDir PathToProfileDir newuser 45206 /bin/cmd cmd Last
17  * First Middle 2 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
18  *
19  * login, unix_uid, shell, winconsoleshell, last, first, middle, status, 
20  * mitid, type, moiraid
21  *
22  * arguments for deactivating/deleting a user account
23  * users 11 11 username 45206 /bin/cmd cmd Last First Middle 1 950000001 STAFF
24  * 121058  PathToHomeDir PathToProfileDir username 45206 /bin/cmd cmd Last
25  * First Middle 3 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
26  * users 11 11 username 45206 /bin/cmd cmd Last First Middle 2 950000001 STAFF
27  * 121058  PathToHomeDir PathToProfileDir username 45206 /bin/cmd cmd Last
28  * First Middle 3 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
29  * 
30  * login, unix_uid, shell, winconsoleshell, last, first, middle, status,
31  * mitid, type, moiraid
32  *
33  * arguments for reactivating a user account
34  * users 11 11 username 45206 /bin/cmd cmd Last First Middle 3 950000001 STAFF
35  * 121058 username 45206 /bin/cmd cmd Last First Middle 1 950000001 STAFF
36  * 121058
37  * users 11 11 username 45206 /bin/cmd cmd Last First Middle 3 950000001 STAFF
38  * 121058 username 45206 /bin/cmd cmd Last First Middle 2 950000001 STAFF 12105
39  *
40  * login, unix_uid, shell, winconsoleshell, last, first, middle, status, 
41  * mitid, type, moiraid
42  *
43  * arguments for changing user name
44  * users 11 11 oldusername 45206 /bin/cmd cmd Last First Middle 1 950000001 
45  * STAFF 121058 PathToHomeDir PathToProfileDir newusername 45206 /bin/cmd cmd 
46  * Last First Middle 1 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
47  *
48  * login, unix_uid, shell, winconsoleshell, last, first, middle, status, 
49  * mitid, type, moiraid
50  *
51  * arguments for expunging a user
52  * users 11 0 username 45198 /bin/cmd cmd Last First Middle 0 950000001 2000
53  * 121049
54  *
55  * login, unix_uid, shell, winconsoleshell, last, first, middle, status, 
56  * mitid, type, moiraid
57  *
58  * arguments for creating a "special" group/list
59  * list 0 11 listname 1 1 0 0 0 -1 NONE 0 description 92616
60  *
61  * listname, active, publicflg, hidden, maillist, grouplist, gid, acl_type, 
62  * acl_id, description, moiraid
63  * 
64  * arguments for creating a "mail" group/list
65  * list 0 11 listname 1 1 0 1 0 -1 NONE 0 description 92616
66  *
67  * listname, active, publicflg, hidden, maillist, grouplist, gid, acl_type, 
68  * acl_id, description, moiraid
69  *
70  * arguments for creating a "group" group/list
71  * list 0 11 listname 1 1 0 0 1 -1 NONE 0 description 92616
72  * 
73  * listname, active, publicflg, hidden, maillist, grouplist, gid, acl_type, 
74  * acl_id, description, moiraid
75  *
76  * arguments for creating a "group/mail" group/list
77  * list 0 11 listname 1 1 0 1 1 -1 NONE 0 description 92616
78  *
79  * listname, active, publicflg, hidden, maillist, grouplist, gid, acl_type, 
80  * acl_id, description, moiraid
81  *
82  * arguments to add a USER member to group/list
83  * imembers 0 12 listname USER userName 1 1 0 0 0 -1 1 92616 121047
84  *
85  * list_name, user_type, name, active, publicflg, hidden, maillist, grouplist,
86  * gid, userStatus, moiraListId, moiraUserId
87  *
88  * arguments to add a STRING or KERBEROS member to group/list
89  * imembers 0 10 listname STRING stringName 1 1 0 0 0 -1 92616
90  * imembers 0 10 listlistnameName KERBEROS kerberosName 1 1 0 0 0 -1 92616
91  *
92  * list_name, user_type, name, active, publicflg, hidden, maillist, grouplist,
93  * gid, moiraListId
94  *
95  * NOTE: group members of type LIST are ignored.
96  *
97  * arguments to remove a USER member to group/list
98  * imembers 12 0 listname USER userName 1 1 0 0 0 -1 1 92616 121047
99  * 
100  * list_name, user_type, name, active, publicflg, hidden, maillist, grouplist,
101  * gid, userStatus, moiraListId, moiraUserId
102  *
103  * arguments to remove a STRING or KERBEROS member to group/list
104  * imembers 10 0 listname STRING stringName 1 1 0 0 0 -1 92616
105  * imembers 10 0 listname KERBEROS kerberosName 1 1 0 0 0 -1 92616
106  *
107  * list_name, user_type, name, active, publicflg, hidden, maillist, grouplist,
108  * gid, moiraListId
109  *
110  * NOTE: group members of type LIST are ignored.
111  *
112  * arguments for renaming a group/list
113  * list 11 11 oldlistname 1 1 0 0 0 -1 NONE 0 description 92616 newlistname 1
114  * 1 0 0 0 -1 description 0 92616
115  * 
116  * name, active, publicflg, hidden, maillist, grouplist, gid, acl_type, 
117  * acl_id, description, moiraListId
118  *
119  * arguments for deleting a group/list
120  * list 11 0 listname 1 1 0 0 0 -1 NONE 0 description 92616
121  *
122  * name, active, publicflg, hidden, maillist, grouplist, gid, acl_type, 
123  * acl_id, description, moiraListId
124  *
125  * arguments for adding a file system
126  * filesys 0 12 username AFS ATHENA.MIT.EDU 
127  * /afs/athena.mit.edu/user/n/e/username /mit/username w descripton username
128  * wheel 1 HOMEDIR 101727
129  *
130  * arguments for deleting a file system
131  * filesys 12 0 username AFS ATHENA.MIT.EDU 
132  * /afs/athena.mit.edu/user/n/e/username /mit/username w descripton username
133  * wheel 1 HOMEDIR 101727
134  *
135  * arguments when moira creates a container (OU).
136  * containers 0 8 machines/test/bottom description location contact USER
137  * 105316 2222 [none]
138  *
139  * arguments when moira deletes a container (OU).
140  * containers 8 0 machines/test/bottom description location contact USER 
141  * 105316 2222 groupname
142  *
143  * arguments when moira modifies a container information (OU).
144  * containers 8 8 machines/test/bottom description location contact USER 
145  * 105316 2222 groupname machines/test/bottom description1 location contact 
146  * USER 105316 2222 groupname
147  *
148  * arguments when moira adds a machine from an OU
149  * table name, beforec, afterc, machine_name, container_name, mach_id, cnt_id
150  * mcntmap 0 5 DAVIDT.MIT.EDU dttest/dttest1 76767 46 groupname
151  *
152  * arguments when moira removes a machine from an OU
153  * table name, beforec, afterc, machine_name, container_name, mach_id, cnt_id
154  * mcntmap 0 5 DAVIDT.MIT.EDU dttest/dttest1 76767 46 groupname
155  *
156 */
157
158 #include <mit-copyright.h>
159
160 #ifdef _WIN32
161 #include <winsock2.h>
162 #include <windows.h>
163 #include <stdlib.h>
164 #include <malloc.h>
165 #include <lmaccess.h>
166 #endif
167
168 #include <hesiod.h>
169 #include <string.h>
170 #include <ldap.h>
171 #include <stdio.h>
172 #include <moira.h>
173 #include <moira_site.h>
174 #include <mrclient.h>
175 #include <krb5.h>
176 #include <gsssasl.h>
177 #include <gssldap.h> 
178 #include "kpasswd.h"
179
180 #ifdef _WIN32
181 #ifndef ECONNABORTED
182 #define ECONNABORTED WSAECONNABORTED
183 #endif
184 #ifndef ECONNREFUSED
185 #define ECONNREFUSED WSAECONNREFUSED
186 #endif
187 #ifndef EHOSTUNREACH
188 #define EHOSTUNREACH WSAEHOSTUNREACH
189 #endif
190 #define krb5_xfree free
191 #define F_OK 0
192 #define sleep(A) Sleep(A * 1000);
193 #endif /* _WIN32 */
194
195 #ifndef _WIN32
196 #include <sys/types.h>
197 #include <netinet/in.h>
198 #include <arpa/nameser.h>
199 #include <resolv.h>
200 #include <sys/utsname.h>
201 #include <unistd.h>
202
203 #define CFG_PATH "/moira/ldap/"
204 #define WINADCFG "ldap.cfg"
205 #define strnicmp(A,B,C) strncasecmp(A,B,C)
206 #define UCHAR unsigned char
207
208 #define UF_SCRIPT               0x0001
209 #define UF_ACCOUNTDISABLE       0x0002
210 #define UF_HOMEDIR_REQUIRED     0x0008
211 #define UF_LOCKOUT              0x0010
212 #define UF_PASSWD_NOTREQD       0x0020
213 #define UF_PASSWD_CANT_CHANGE   0x0040
214 #define UF_DONT_EXPIRE_PASSWD   0x10000
215
216 #define UF_TEMP_DUPLICATE_ACCOUNT       0x0100
217 #define UF_NORMAL_ACCOUNT               0x0200
218 #define UF_INTERDOMAIN_TRUST_ACCOUNT    0x0800
219 #define UF_WORKSTATION_TRUST_ACCOUNT    0x1000
220 #define UF_SERVER_TRUST_ACCOUNT         0x2000
221
222 #define OWNER_SECURITY_INFORMATION       (0x00000001L)
223 #define GROUP_SECURITY_INFORMATION       (0x00000002L)
224 #define DACL_SECURITY_INFORMATION        (0x00000004L)
225 #define SACL_SECURITY_INFORMATION        (0x00000008L)
226
227 #ifndef BYTE
228 #define BYTE unsigned char
229 #endif
230 typedef unsigned int DWORD;
231 typedef unsigned long ULONG;
232
233 typedef struct _GUID
234 {
235   unsigned long Data1;
236   unsigned short Data2;
237   unsigned short Data3;
238   unsigned char Data4[8];
239 } GUID;
240
241 typedef struct _SID_IDENTIFIER_AUTHORITY { 
242   BYTE Value[6]; 
243 } SID_IDENTIFIER_AUTHORITY, *PSID_IDENTIFIER_AUTHORITY; 
244
245 typedef struct _SID {
246   BYTE  Revision;
247   BYTE  SubAuthorityCount;
248   SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
249   DWORD SubAuthority[512];
250 } SID;
251 #endif/*!WIN32*/
252
253 #ifndef WINADCFG
254 #define WINADCFG "ldap.cfg"
255 #endif
256
257 #ifndef CFG_PATH
258 #define CFG_PATH ""
259 #endif 
260
261 #define AFS "/afs/"
262 #define WINAFS "\\\\afs\\all\\"
263
264 #define ADS_GROUP_TYPE_GLOBAL_GROUP         0x00000002
265 #define ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP   0x00000004
266 #define ADS_GROUP_TYPE_LOCAL_GROUP          0x00000004
267 #define ADS_GROUP_TYPE_UNIVERSAL_GROUP      0x00000008
268 #define ADS_GROUP_TYPE_SECURITY_ENABLED     0x80000000
269
270 #define QUERY_VERSION   -1
271 #define PRIMARY_REALM   "ATHENA.MIT.EDU"
272 #define PRIMARY_DOMAIN  "win.mit.edu"
273 #define PRODUCTION_PRINCIPAL "sms"
274 #define TEST_PRINCIPAL       "smstest"
275
276 #define SUBSTITUTE  1
277 #define REPLACE     2
278
279 #define USERS         0
280 #define GROUPS        1
281
282 #define MEMBER_ADD          1
283 #define MEMBER_REMOVE       2
284 #define MEMBER_CHANGE_NAME  3
285 #define MEMBER_ACTIVATE     4
286 #define MEMBER_DEACTIVATE   5
287 #define MEMBER_CREATE       6
288
289 #define MOIRA_ALL       0x0
290 #define MOIRA_USERS     0x1
291 #define MOIRA_KERBEROS  0x2
292 #define MOIRA_STRINGS   0x4
293 #define MOIRA_LISTS     0x8
294 #define MOIRA_MACHINE   0x16
295
296 #define CHECK_GROUPS    1
297 #define CLEANUP_GROUPS  2
298
299 #define AD_NO_GROUPS_FOUND        -1
300 #define AD_WRONG_GROUP_DN_FOUND   -2
301 #define AD_MULTIPLE_GROUPS_FOUND  -3
302 #define AD_INVALID_NAME           -4
303 #define AD_LDAP_FAILURE           -5
304 #define AD_INVALID_FILESYS        -6
305 #define AD_NO_ATTRIBUTE_FOUND     -7
306 #define AD_NO_OU_FOUND            -8
307 #define AD_NO_USER_FOUND          -9
308
309 /* container arguments */
310 #define CONTAINER_NAME       0
311 #define CONTAINER_DESC       1
312 #define CONTAINER_LOCATION   2
313 #define CONTAINER_CONTACT    3
314 #define CONTAINER_TYPE       4
315 #define CONTAINER_ID         5
316 #define CONTAINER_ROWID      6
317 #define CONTAINER_GROUP_NAME 7
318
319 /*mcntmap arguments*/
320 #define OU_MACHINE_NAME        0
321 #define OU_CONTAINER_NAME      1
322 #define OU_MACHINE_ID          2
323 #define OU_CONTAINER_ID        3
324 #define OU_CONTAINER_GROUP     4
325
326 typedef struct lk_entry {
327   int     op;
328   int     length;
329   int     ber_value;
330   char    *dn;
331   char    *attribute;
332   char    *value;
333   char    *member;
334   char    *type;
335   char    *list;
336   struct  lk_entry *next;
337 } LK_ENTRY;
338
339 #define STOP_FILE "/moira/ldap/noldap"
340 #define file_exists(file) (access((file), F_OK) == 0)
341
342 #define N_SD_BER_BYTES   5
343 #define LDAP_BERVAL struct berval
344 #define MAX_SERVER_NAMES 32
345
346 #define HIDDEN_GROUP                "HiddenGroup.g"
347 #define HIDDEN_GROUP_WITH_ADMIN     "HiddenGroupWithAdmin.g"
348 #define NOT_HIDDEN_GROUP            "NotHiddenGroup.g"
349 #define NOT_HIDDEN_GROUP_WITH_ADMIN "NotHiddenGroupWithAdmin.g"
350
351 #define ADDRESS_LIST_PREFIX "CN=MIT Directory,CN=All Address Lists,\
352 CN=Address Lists Container,CN=Massachusetts Institute of Technology,\
353 CN=Microsoft Exchange,CN=Services,CN=Configuration,"
354
355 #define GLOBAL_ADDRESS_LIST_PREFIX "CN=Default Global Address List,\
356 CN=All Global Address Lists,CN=Address Lists Container,\
357 CN=Massachusetts Institute of Technology,CN=Microsoft Exchange,CN=Services,\
358 CN=Configuration,"
359
360 #define EMAIL_ADDRESS_LIST_PREFIX "CN=Email Users,CN=All Users,\
361 CN=All Address Lists,CN=Address Lists Container,\
362 CN=Massachusetts Institute of Technology,CN=Microsoft Exchange,\
363 CN=Services,CN=Configuration,"
364
365 #define ALL_ADDRESS_LIST_PREFIX "CN=All Users,CN=All Address Lists,\
366 CN=Address Lists Container,CN=Massachusetts Institute of Technology,\
367 CN=Microsoft Exchange,CN=Services,CN=Configuration,"
368
369 #define ADD_ATTR(t, v, o)               \
370   mods[n] = malloc(sizeof(LDAPMod));    \
371   mods[n]->mod_op = o;                  \
372   mods[n]->mod_type = t;                \
373   mods[n++]->mod_values = v
374
375 #define DEL_ATTR(t, o)                  \
376   DelMods[i] = malloc(sizeof(LDAPMod)); \
377   DelMods[i]->mod_op = o;               \
378   DelMods[i]->mod_type = t;             \
379   DelMods[i++]->mod_values = NULL
380
381 #define DOMAIN_SUFFIX   "MIT.EDU"
382 #define DOMAIN  "DOMAIN:"
383 #define PRINCIPALNAME  "PRINCIPAL:"
384 #define SERVER  "SERVER:"
385 #define MSSFU   "SFU:"
386 #define SFUTYPE "30"
387 #define GROUP_SUFFIX "GROUP_SUFFIX:"
388 #define GROUP_TYPE   "GROUP_TYPE:"
389 #define SET_GROUP_ACE    "SET_GROUP_ACE:"
390 #define SET_PASSWORD "SET_PASSWORD:"
391 #define EXCHANGE "EXCHANGE:"
392 #define REALM "REALM:"
393 #define ACTIVE_DIRECTORY "ACTIVE_DIRECTORY:"
394 #define PORT "PORT:"
395 #define PROCESS_MACHINE_CONTAINER "PROCESS_MACHINE_CONTAINER:"
396 #define GROUP_POPULATE_MEMBERS "GROUP_POPULATE_MEMBERS:"
397 #define MAX_MEMBERS "MAX_MEMBERS:"
398 #define MAX_DOMAINS 10
399 char DomainNames[MAX_DOMAINS][128];
400
401 LK_ENTRY *member_base = NULL;
402
403 char   PrincipalName[128];
404 static char tbl_buf[1024];
405 char  kerberos_ou[] = "OU=kerberos,OU=moira";
406 char  contact_ou[] = "OU=strings,OU=moira";
407 char  user_ou[] = "OU=users,OU=moira";
408 char  group_ou_distribution[1024];
409 char  group_ou_root[1024];
410 char  group_ou_security[1024];
411 char  group_ou_neither[1024];
412 char  group_ou_both[1024]; 
413 char  orphans_machines_ou[] = "OU=Machines,OU=Orphans";
414 char  orphans_other_ou[] = "OU=Other,OU=Orphans";
415 char  security_template_ou[] = "OU=security_templates";
416 char *whoami;
417 char ldap_domain[256];
418 char ldap_realm[256];
419 char ldap_port[256];
420 char *ServerList[MAX_SERVER_NAMES];
421 char default_server[256];
422 static char tbl_buf[1024];
423 char group_suffix[256];
424 char exchange_acl[256];
425 int  mr_connections = 0;
426 int  callback_rc;
427 int  UseSFU30 = 0;
428 int  UseGroupSuffix = 1;
429 int  UseGroupUniversal = 0;
430 int  SetGroupAce = 1;
431 int  SetPassword = 1;
432 int  Exchange = 0;
433 int  ProcessMachineContainer = 1;
434 int  ActiveDirectory = 1;
435 int  UpdateDomainList;
436 int  fsgCount;
437 int  GroupPopulateDelete = 0;
438 int  group_members = 0;
439 int  max_group_members = 0;
440
441 extern int set_password(char *user, char *password, char *domain);
442
443 int ad_get_group(LDAP *ldap_handle, char *dn_path, char *group_name, 
444                  char *group_membership, char *MoiraId, char *attribute,
445                  LK_ENTRY **linklist_base, int *linklist_count,
446                  char *rFilter);
447 void AfsToWinAfs(char* path, char* winPath);
448 int ad_connect(LDAP **ldap_handle, char *ldap_domain, char *dn_path, 
449                char *Win2kPassword, char *Win2kUser, char *default_server,
450                int connect_to_kdc, char **ServerList, char *ldap_realm,
451                char *ldap_port);
452 void ad_kdc_disconnect();
453 int ad_server_connect(char *connectedServer, char *domain);
454 int attribute_update(LDAP *ldap_handle, char *distinguished_name, 
455                      char *attribute_value, char *attribute, char *user_name);
456 int BEREncodeSecurityBits(ULONG uBits, char *pBuffer);
457 int checkADname(LDAP *ldap_handle, char *dn_path, char *Name);
458 int check_winad(void);
459 int check_user(LDAP *ldap_handle, char *dn_path, char *UserName, 
460                char *MoiraId);
461 /* containers */
462 int container_adupdate(LDAP *ldap_handle, char *dn_path, char *dName, 
463                        char *distinguishedName, int count, char **av);
464 void container_check(LDAP *ldap_handle, char *dn_path, char *name);
465 int container_create(LDAP *ldap_handle, char *dn_path, int count, char **av);
466 int container_delete(LDAP *ldap_handle, char *dn_path, int count, char **av);
467 int container_get_distinguishedName(LDAP *ldap_handle, char *dn_path, 
468                                     char *distinguishedName, int count, 
469                                     char **av);
470 void container_get_dn(char *src, char *dest);
471 void container_get_name(char *src, char *dest);
472 int container_move_objects(LDAP *ldap_handle, char *dn_path, char *dName);
473 int container_rename(LDAP *ldap_handle, char *dn_path, int beforec, 
474                      char **before, int afterc, char **after);
475 int container_update(LDAP *ldap_handle, char *dn_path, int beforec, 
476                      char **before, int afterc, char **after);
477
478 int GetAceInfo(int ac, char **av, void *ptr);
479 int get_group_membership(char *group_membership, char *group_ou, 
480                          int *security_flag, char **av);
481 int get_machine_ou(LDAP *ldap_handle, char *dn_path, char *member, 
482                    char *machine_ou, char *pPtr);
483 int Moira_container_group_create(char **after);
484 int Moira_container_group_delete(char **before);
485 int Moira_groupname_create(char *GroupName, char *ContainerName,
486                            char *ContainerRowID);
487 int Moira_container_group_update(char **before, char **after);
488 int Moira_process_machine_container_group(char *MachineName, char* groupName,
489                                           int DeleteMachine);
490 int Moira_addGroupToParent(char *origContainerName, char *GroupName);
491 int Moira_getContainerGroup(int ac, char **av, void *ptr);
492 int Moira_getGroupName(char *origContainerName, char *GroupName,
493                        int ParentFlag);
494 int Moira_setContainerGroup(char *ContainerName, char *GroupName);
495 int ProcessAce(LDAP *ldap_handle, char *dn_path, char *group_name, char *Type,
496                int UpdateGroup, int *ProcessGroup, char *maillist,
497                char *nfsgroup);
498 int process_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
499                   char *group_name, char *group_ou, char *group_membership, 
500                   int group_security_flag, int type, char *maillist,
501                   char *nfsgroup);
502 int process_lists(int ac, char **av, void *ptr);
503 int ProcessGroupSecurity(LDAP *ldap_handle, char *dn_path, 
504                          char *TargetGroupName, int HiddenGroup, 
505                          char *AceType, char *AceName);
506 int ProcessMachineName(int ac, char **av, void *ptr);
507 int ReadConfigFile(char *DomainName);
508 int ReadDomainList();
509 void StringTrim(char *StringToTrim);
510 char *escape_string(char *s);
511 int save_query_info(int argc, char **argv, void *hint);
512 int save_fsgroup_info(int argc, char **argv, void *hint);
513 int user_create(int ac, char **av, void *ptr);
514 int user_change_status(LDAP *ldap_handle, char *dn_path, 
515                        char *user_name, char *MoiraId, int operation);
516 int user_delete(LDAP *ldap_handle, char *dn_path, 
517                 char *u_name, char *MoiraId);
518 int user_rename(LDAP *ldap_handle, char *dn_path, char *before_user_name, 
519                 char *user_name);
520 int user_update(LDAP *ldap_handle, char *dn_path, char *user_name,
521                 char *uid, char *MitId, char *MoiraId, int State,
522                 char *WinHomeDir, char *WinProfileDir, char *first,
523                 char *middle, char *last, char *shell, char *class);
524 void change_to_lower_case(char *ptr);
525 int contact_create(LDAP *ld, char *bind_path, char *user, char *group_ou);
526 int contact_remove_email(LDAP *ld, char *bind_path,
527                          LK_ENTRY **linklist_entry, int linklist_current);
528 int group_create(int ac, char **av, void *ptr);
529 int group_delete(LDAP *ldap_handle, char *dn_path, 
530                  char *group_name, char *group_membership, char *MoiraId);
531 int group_rename(LDAP *ldap_handle, char *dn_path, 
532                  char *before_group_name, char *before_group_membership, 
533                  char *before_group_ou, int before_security_flag, 
534                  char *before_desc, char *after_group_name, 
535                  char *after_group_membership, char *after_group_ou, 
536                  int after_security_flag, char *after_desc,
537                  char *MoiraId, char *filter, char *maillist, char *nfsgroup);
538 int machine_check(LDAP *ldap_handle, char *dn_path, char *machine_name);
539 int machine_GetMoiraContainer(int ac, char **av, void *ptr);
540 int machine_get_moira_container(LDAP *ldap_handle, char *dn_path, 
541                                 char *machine_name, char *container_name);
542 int machine_move_to_ou(LDAP *ldap_handle, char *dn_path, 
543                        char *MoiraMachineName, char *DestinationOu);
544 int make_new_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
545                    char *group_name, char *group_ou, char *group_membership, 
546                    int group_security_flag, int updateGroup, char *maillist,
547                    char *nfsgroup);
548 int member_list_build(int ac, char **av, void *ptr);
549 int member_add(LDAP *ldap_handle, char *dn_path, char *group_name, 
550                char *group_ou, char *group_membership, 
551                char *user_name, char *pUserOu, char *MoiraId);
552 int member_remove(LDAP *ldap_handle, char *dn_path, char *group_name, 
553                   char *group_ou, char *group_membership, char *user_name,
554                   char *pUserOu, char *MoiraId);
555 int contains_member(LDAP *ldap_handle, char *dn_path, char *group_name,
556                    char *UserOu, char *member);
557 int populate_group(LDAP *ldap_handle, char *dn_path, char *group_name, 
558                    char *group_ou, char *group_membership, 
559                    int group_security_flag, char *MoiraId, int synchronize);
560 int SetHomeDirectory(LDAP *ldap_handle, char *user_name, 
561                      char *DistinguishedName,
562                      char *WinHomeDir, char *WinProfileDir,
563                      char **homedir_v, char **winProfile_v,
564                      char **drives_v, LDAPMod **mods, 
565                      int OpType, int n);
566 int sid_update(LDAP *ldap_handle, char *dn_path);
567 void SwitchSFU(LDAPMod **mods, int *UseSFU30, int n);
568 int check_string(char *s);
569 int check_container_name(char* s);
570
571 int mr_connect_cl(char *server, char *client, int version, int auth);
572 void do_container(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
573                   char **before, int beforec, char **after, int afterc);
574 void do_filesys(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
575                 char **before, int beforec, char **after, int afterc);
576 void do_list(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
577              char **before, int beforec, char **after, int afterc);
578 void do_user(LDAP *ldap_handle, char *dn_path, char *ldap_hostname, 
579              char **before, int beforec, char **after, int afterc);
580 void do_member(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
581                char **before, int beforec, char **after, int afterc);
582 void do_mcntmap(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
583                 char **before, int beforec, char **after, int afterc);
584 int linklist_create_entry(char *attribute, char *value,
585                           LK_ENTRY **linklist_entry);
586 int linklist_build(LDAP *ldap_handle, char *dn_path, char *search_exp, 
587                    char **attr_array, LK_ENTRY **linklist_base, 
588                    int *linklist_count, unsigned long ScopeType);
589 void linklist_free(LK_ENTRY *linklist_base);
590
591 int retrieve_attributes(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
592                         char *distinguished_name, LK_ENTRY **linklist_current);
593 int retrieve_entries(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
594                      LK_ENTRY **linklist_base, int *linklist_count);
595 int retrieve_values(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
596                     char *Attribute, char *distinguished_name, 
597                     LK_ENTRY **linklist_current);
598
599 int construct_newvalues(LK_ENTRY *linklist_base, int modvalue_count, 
600                         char *oldValue, char *newValue,
601                         char ***modvalues, int type);
602 void free_values(char **modvalues);
603
604 int convert_domain_to_dn(char *domain, char **bind_path);
605 void get_distinguished_name(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
606                             char *distinguished_name);
607 int moira_disconnect(void);
608 int moira_connect(void);
609 void print_to_screen(const char *fmt, ...);
610 int GetMachineName(char *MachineName);
611 int tickets_get_k5();
612 int destroy_cache(void);
613 int dest_tkt(void);
614
615 int find_homeMDB(LDAP *ldap_handle, char *dn_path, char **homeMDB,
616                  char **homeServerName);
617
618 int main(int argc, char **argv)
619 {
620   unsigned long   rc;
621   int             beforec;
622   int             afterc;
623   int             i;
624   int             j;
625   int             k;
626   int             OldUseSFU30;
627   char            *table;
628   char            **before;
629   char            **after;
630   LDAP            *ldap_handle;
631   char            dn_path[256];
632   char            *orig_argv[64];
633   
634   whoami = ((whoami = (char *)strrchr(argv[0], '/')) ? whoami+1 : argv[0]);
635   
636   if (argc < 4)
637     {
638       com_err(whoami, 0, "Unable to process %s", "argc < 4");
639       exit(1);
640     }
641   
642   if (argc < (4 + atoi(argv[2]) + atoi(argv[3])))
643     {
644       com_err(whoami, 0, "Unable to process %s", 
645               "argc < (4 + beforec + afterc)");
646       exit(1);
647     }
648
649   if (!strcmp(argv[1], "filesys"))
650     exit(0);
651
652   for (i = 1; i < argc; i++)
653     {
654       strcat(tbl_buf, argv[i]);
655       strcat(tbl_buf, " ");
656     }
657
658   com_err(whoami, 0, "%s", tbl_buf);
659
660   if (check_winad())
661     {
662       com_err(whoami, 0, "%s failed", "check_winad()");
663       exit(1);
664     }
665
666   initialize_sms_error_table();
667   initialize_krb_error_table();
668
669   UpdateDomainList = 0;
670   memset(DomainNames, '\0', sizeof(DomainNames[0]) * MAX_DOMAINS);
671
672   if (ReadDomainList())
673     {
674       com_err(whoami, 0, "%s failed", "ReadDomainList()");
675       exit(1);
676     }
677
678   for (i = 0; i < argc; i++)
679      orig_argv[i] = NULL;
680
681   for (k = 0; k < MAX_DOMAINS; k++)
682     {
683       if (strlen(DomainNames[k]) == 0)
684         continue;
685       for (i = 0; i < argc; i++)
686         {
687           if (orig_argv[i] != NULL)
688             free(orig_argv[i]);
689           orig_argv[i] = strdup(argv[i]);
690         }
691
692       memset(PrincipalName, '\0', sizeof(PrincipalName));
693       memset(ldap_domain, '\0', sizeof(ldap_domain));
694       memset(ServerList, '\0', sizeof(ServerList[0]) * MAX_SERVER_NAMES);
695       memset(default_server, '\0', sizeof(default_server));
696       memset(dn_path, '\0', sizeof(dn_path));
697       memset(group_suffix, '\0', sizeof(group_suffix));
698       memset(exchange_acl, '\0', sizeof(exchange_acl));
699
700       UseSFU30 = 0;
701       UseGroupSuffix = 1;
702       UseGroupUniversal = 0;
703       SetGroupAce = 1;
704       SetPassword = 1;
705       Exchange = 0;
706       ProcessMachineContainer = 1;
707       ActiveDirectory = 1;
708
709       sprintf(group_suffix, "%s", "_group");
710       sprintf(exchange_acl, "%s", "exchange-acl");
711
712       beforec = atoi(orig_argv[2]);
713       afterc = atoi(orig_argv[3]);
714       table = orig_argv[1];
715       before = &orig_argv[4];
716       after = &orig_argv[4 + beforec];
717
718       if (afterc == 0)
719         after = NULL;
720
721       if (beforec == 0)
722         before = NULL;
723
724       if (ReadConfigFile(DomainNames[k]))
725         continue;
726
727       if(ActiveDirectory)
728         {
729           sprintf(group_ou_distribution, "OU=mail,OU=lists,OU=moira");
730           sprintf(group_ou_root, "OU=lists,OU=moira");
731           sprintf(group_ou_security, "OU=group,OU=lists,OU=moira");
732           sprintf(group_ou_neither, "OU=special,OU=lists,OU=moira");
733           sprintf(group_ou_both, "OU=mail,OU=group,OU=lists,OU=moira");
734         }
735       else
736         {
737           sprintf(group_ou_distribution, "OU=lists,OU=moira");
738           sprintf(group_ou_root, "OU=lists,OU=moira");
739           sprintf(group_ou_security, "OU=lists,OU=moira");
740           sprintf(group_ou_neither, "OU=lists,OU=moira");
741           sprintf(group_ou_both, "OU=lists,OU=moira");
742         }
743
744       OldUseSFU30 = UseSFU30;
745
746       for (i = 0; i < 5; i++)
747         {
748           ldap_handle = (LDAP *)NULL;
749           if (!(rc = ad_connect(&ldap_handle, ldap_domain, dn_path, "", "", 
750                                 default_server, SetPassword, ServerList, 
751                                 ldap_realm, ldap_port)))
752             {
753               com_err(whoami, 0, "connected to domain %s", DomainNames[k]);
754               break;
755             }
756         }
757
758       if ((rc) || (ldap_handle == NULL))
759         {
760           critical_alert("incremental",
761                          "ldap.incr cannot connect to any server in "
762                          "domain %s", DomainNames[k]);
763           continue;
764         }
765
766       for (i = 0; i < (int)strlen(table); i++)
767         table[i] = tolower(table[i]);
768
769       if (!strcmp(table, "users"))
770         do_user(ldap_handle, dn_path, ldap_domain, before, beforec, after,
771                 afterc);
772       else if (!strcmp(table, "list"))
773         do_list(ldap_handle, dn_path, ldap_domain, before, beforec, after,
774                 afterc);
775       else if (!strcmp(table, "imembers"))
776         do_member(ldap_handle, dn_path, ldap_domain, before, beforec, after,
777                   afterc);
778       else if (!strcmp(table, "containers"))
779         do_container(ldap_handle, dn_path, ldap_domain, before, beforec, after,
780                      afterc);
781       else if (!strcmp(table, "mcntmap"))
782         do_mcntmap(ldap_handle, dn_path, ldap_domain, before, beforec, after,
783                    afterc);
784
785       if(SetPassword) 
786         ad_kdc_disconnect();
787
788       for (i = 0; i < MAX_SERVER_NAMES; i++)
789         {
790           if (ServerList[i] != NULL)
791             {
792               free(ServerList[i]);
793               ServerList[i] = NULL;
794             }
795         }
796       
797       rc = ldap_unbind_s(ldap_handle);
798     }
799   
800   exit(0);
801 }
802
803 void do_mcntmap(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
804                 char **before, int beforec, char **after, int afterc)
805 {
806   char    MoiraContainerName[128];
807   char    ADContainerName[128];
808   char    MachineName[1024];
809   char    OriginalMachineName[1024];
810   long    rc;
811   int     DeleteMachine;
812   char    MoiraContainerGroup[64];
813
814   if (!ProcessMachineContainer)
815     {
816       com_err(whoami, 0, "Process machines and containers disabled, skipping");
817       return;
818     }
819   
820   DeleteMachine = 0;
821   memset(ADContainerName, '\0', sizeof(ADContainerName));
822   memset(MoiraContainerName, '\0', sizeof(MoiraContainerName));
823   
824   if ((beforec == 0) && (afterc == 0))
825     return;
826   
827   if (rc = moira_connect())
828     {
829       critical_alert("Ldap incremental",
830                      "Error contacting Moira server : %s",
831                      error_message(rc));
832       return;
833     }
834   
835   if ((beforec != 0) && (afterc == 0)) /*remove a machine*/
836     {
837       strcpy(OriginalMachineName, before[OU_MACHINE_NAME]);
838       strcpy(MachineName, before[OU_MACHINE_NAME]);
839       strcpy(MoiraContainerGroup, before[OU_CONTAINER_GROUP]);
840       DeleteMachine = 1;
841       com_err(whoami, 0, "removing machine %s from %s", 
842               OriginalMachineName, before[OU_CONTAINER_NAME]);
843     }
844   else if ((beforec == 0) && (afterc != 0)) /*add a machine*/
845     {
846       strcpy(OriginalMachineName, after[OU_MACHINE_NAME]);
847       strcpy(MachineName, after[OU_MACHINE_NAME]);
848       strcpy(MoiraContainerGroup, after[OU_CONTAINER_GROUP]);
849       com_err(whoami, 0, "adding machine %s to container %s", 
850               OriginalMachineName, after[OU_CONTAINER_NAME]);
851     }
852   else
853     {
854       moira_disconnect();
855       return;
856     }
857   
858   rc = GetMachineName(MachineName);
859
860   if (strlen(MachineName) == 0)
861     {
862       moira_disconnect();
863       com_err(whoami, 0, "Unable to find alais for machine %s in Moira", 
864               OriginalMachineName);
865       return;
866     }
867
868   Moira_process_machine_container_group(MachineName, MoiraContainerGroup,
869                                         DeleteMachine);
870
871   if (machine_check(ldap_handle, dn_path, MachineName))
872     {
873       com_err(whoami, 0, "Unable to find machine %s (alias %s) in directory.", 
874               OriginalMachineName, MachineName);
875       moira_disconnect();
876       return;
877     }
878
879   memset(MoiraContainerName, '\0', sizeof(MoiraContainerName));
880   machine_get_moira_container(ldap_handle, dn_path, MachineName, 
881                               MoiraContainerName);
882
883   if (strlen(MoiraContainerName) == 0)
884     {
885       com_err(whoami, 0, "Unable to fine machine %s (alias %s) container "
886               "in Moira - moving to orphans OU.",
887               OriginalMachineName, MachineName);
888       machine_move_to_ou(ldap_handle, dn_path, MachineName, 
889                          orphans_machines_ou);
890       moira_disconnect();
891       return;
892     }
893
894   container_get_dn(MoiraContainerName, ADContainerName);
895
896   if (MoiraContainerName[strlen(MoiraContainerName) - 1] != '/')
897     strcat(MoiraContainerName, "/");
898
899   container_check(ldap_handle, dn_path, MoiraContainerName);
900   machine_move_to_ou(ldap_handle, dn_path, MachineName, ADContainerName);
901   moira_disconnect();
902   return;
903 }
904
905 void do_container(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
906                   char **before, int beforec, char **after, int afterc)
907 {
908   long rc;
909
910   if (!ProcessMachineContainer)
911     {
912       com_err(whoami, 0, "Process machines and containers disabled, skipping");
913       return;
914     }
915
916   if ((beforec == 0) && (afterc == 0))
917     return;
918
919   if (rc = moira_connect())
920     {
921       critical_alert("Ldap incremental", "Error contacting Moira server : %s",
922                      error_message(rc));
923       return;
924     }
925
926   if ((beforec != 0) && (afterc == 0)) /*delete a new container*/
927     {
928       com_err(whoami, 0, "deleting container %s", before[CONTAINER_NAME]);
929       container_delete(ldap_handle, dn_path, beforec, before);
930       Moira_container_group_delete(before);
931       moira_disconnect();
932       return;
933     }
934
935   if ((beforec == 0) && (afterc != 0)) /*create a container*/
936     {
937       com_err(whoami, 0, "creating container %s", after[CONTAINER_NAME]);
938       container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
939       container_create(ldap_handle, dn_path, afterc, after);
940       Moira_container_group_create(after);
941       moira_disconnect();
942       return;
943     }
944
945   if (strcasecmp(before[CONTAINER_NAME], after[CONTAINER_NAME]))
946     {
947       com_err(whoami, 0, "renaming container %s to %s", 
948               before[CONTAINER_NAME], after[CONTAINER_NAME]);
949       container_rename(ldap_handle, dn_path, beforec, before, afterc, after);
950       Moira_container_group_update(before, after);
951       moira_disconnect();
952       return;
953     }
954
955   com_err(whoami, 0, "updating container %s information", 
956           after[CONTAINER_NAME]);
957   container_update(ldap_handle, dn_path, beforec, before, afterc, after);
958   Moira_container_group_update(before, after);
959   moira_disconnect();
960   return;
961 }
962
963 #define L_LIST_DESC 9
964 #define L_LIST_ID   10
965 #define L_LIST_NFSGROUP 11
966
967 void do_list(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
968              char **before, int beforec, char **after, int afterc)
969 {
970   int   updateGroup;
971   int   ProcessGroup;
972   long  rc;
973   char  group_membership[6];
974   char  list_id[32];
975   int   security_flag;
976   char  filter[128];
977   char  group_ou[256];
978   char  before_list_id[32];
979   char  before_group_membership[1];
980   int   before_security_flag;
981   char  before_group_ou[256];
982   LK_ENTRY *ptr = NULL;
983
984   if (beforec == 0 && afterc == 0)
985     return;
986
987   memset(list_id, '\0', sizeof(list_id));
988   memset(before_list_id, '\0', sizeof(before_list_id));
989   memset(before_group_ou, '\0', sizeof(before_group_ou));
990   memset(before_group_membership, '\0', sizeof(before_group_membership));
991   memset(group_ou, '\0', sizeof(group_ou));
992   memset(group_membership, '\0', sizeof(group_membership));
993   updateGroup = 0;
994
995   if (beforec > L_GID)
996     {
997       if (beforec < L_LIST_ID)
998         return;
999       if (beforec > L_LIST_DESC)
1000         {
1001           strcpy(before_list_id, before[L_LIST_ID]);
1002         }
1003       before_security_flag = 0;
1004       get_group_membership(before_group_membership, before_group_ou, 
1005                            &before_security_flag, before);
1006     }
1007
1008   if (afterc > L_GID)
1009     {
1010       if (afterc < L_LIST_ID)
1011         return;
1012       if (afterc > L_LIST_DESC)
1013         {
1014           strcpy(list_id, after[L_LIST_ID]);
1015         }
1016       security_flag = 0;
1017       get_group_membership(group_membership, group_ou, &security_flag, after);
1018     }
1019   
1020   if ((beforec == 0) && (afterc == 0)) /*this case should never happen*/
1021     return;
1022
1023   updateGroup = 0;
1024   
1025   if (beforec)
1026     {
1027       updateGroup = 1;
1028
1029       if ((rc = process_group(ldap_handle, dn_path, before_list_id, 
1030                               before[L_NAME], before_group_ou, 
1031                               before_group_membership, 
1032                               before_security_flag, CHECK_GROUPS,
1033                               before[L_MAILLIST], before[L_LIST_NFSGROUP])))
1034         {
1035           if (rc == AD_NO_GROUPS_FOUND)
1036             updateGroup = 0;
1037           else
1038             {
1039               if ((rc == AD_WRONG_GROUP_DN_FOUND) || 
1040                   (rc == AD_MULTIPLE_GROUPS_FOUND))
1041                 {
1042                   rc = process_group(ldap_handle, dn_path, before_list_id, 
1043                                      before[L_NAME], before_group_ou, 
1044                                      before_group_membership, 
1045                                      before_security_flag, CLEANUP_GROUPS,
1046                                      before[L_MAILLIST], 
1047                                      before[L_LIST_NFSGROUP]);
1048                 }
1049               if ((rc != AD_NO_GROUPS_FOUND) && (rc != 0))
1050                 {
1051                   com_err(whoami, 0, "Unable to process list %s",
1052                           before[L_NAME]);
1053                   return;
1054                 }
1055               if (rc == AD_NO_GROUPS_FOUND)
1056                 updateGroup = 0;
1057             }
1058         }
1059     }
1060
1061   if ((beforec != 0) && (afterc != 0))
1062     {
1063       if (((strcmp(after[L_NAME], before[L_NAME])) || 
1064            ((!strcmp(after[L_NAME], before[L_NAME])) && 
1065             (strcmp(before_group_ou, group_ou)))) &&
1066           (updateGroup == 1))
1067         {
1068           com_err(whoami, 0, "Changing list name from %s to %s",
1069                   before[L_NAME], after[L_NAME]);
1070
1071           if ((strlen(before_group_ou) == 0) || 
1072               (strlen(before_group_membership) == 0) ||
1073               (strlen(group_ou) == 0) || (strlen(group_membership) == 0))
1074             {
1075               com_err(whoami, 0, "%s", "Unable to find the group OU's");
1076               return;
1077             }
1078
1079           memset(filter, '\0', sizeof(filter));
1080
1081           if ((rc = group_rename(ldap_handle, dn_path, 
1082                                  before[L_NAME], before_group_membership, 
1083                                  before_group_ou, before_security_flag, 
1084                                  before[L_LIST_DESC], after[L_NAME], 
1085                                  group_membership, group_ou, security_flag, 
1086                                  after[L_LIST_DESC],
1087                                  list_id, filter, after[L_MAILLIST],
1088                                  after[L_LIST_NFSGROUP])))
1089             {
1090               if (rc != AD_NO_GROUPS_FOUND)
1091                 {
1092                   com_err(whoami, 0, 
1093                           "Unable to change list name from %s to %s",
1094                           before[L_NAME], after[L_NAME]);
1095                   return;
1096                 }
1097               updateGroup = 0;
1098             }
1099           beforec = 0;
1100         }
1101       else
1102         beforec = 0;
1103     }
1104   
1105   if (beforec)
1106     {
1107       if ((strlen(before_group_ou) == 0) || 
1108           (strlen(before_group_membership) == 0))
1109         {
1110           com_err(whoami, 0, 
1111                   "Unable to find the group OU for group %s", before[L_NAME]);
1112           return;
1113         }
1114
1115       com_err(whoami, 0, "Deleting group %s", before[L_NAME]);
1116       rc = group_delete(ldap_handle, dn_path, before[L_NAME], 
1117                         before_group_membership, before_list_id);
1118       return;
1119     }
1120
1121   if (afterc)
1122     {
1123       if (!updateGroup)
1124         {
1125           com_err(whoami, 0, "Creating group %s", after[L_NAME]);
1126
1127           if (rc = process_group(ldap_handle, dn_path, list_id, after[L_NAME], 
1128                                   group_ou, group_membership, 
1129                                   security_flag, CHECK_GROUPS,
1130                                  after[L_MAILLIST], after[L_LIST_NFSGROUP]))
1131             {
1132               if (rc != AD_NO_GROUPS_FOUND)
1133                 {
1134                   if ((rc == AD_WRONG_GROUP_DN_FOUND) || 
1135                       (rc == AD_MULTIPLE_GROUPS_FOUND))
1136                     {
1137                       rc = process_group(ldap_handle, dn_path, list_id, 
1138                                          after[L_NAME], 
1139                                          group_ou, group_membership, 
1140                                          security_flag, CLEANUP_GROUPS,
1141                                          after[L_MAILLIST], 
1142                                          after[L_LIST_NFSGROUP]);
1143                     }
1144
1145                   if (rc)
1146                     {
1147                       com_err(whoami, 0, 
1148                               "Unable to create list %s", after[L_NAME]);
1149                       return;
1150                     }
1151                 }
1152             }
1153         }
1154       else
1155         com_err(whoami, 0, "Updating group %s information", after[L_NAME]);
1156
1157       if (rc = moira_connect())
1158         {
1159           critical_alert("Ldap incremental",
1160                          "Error contacting Moira server : %s",
1161                          error_message(rc));
1162           return;
1163         }
1164
1165       ProcessGroup = 0;
1166
1167       if (ProcessAce(ldap_handle, dn_path, after[L_NAME], "LIST", 0, 
1168                      &ProcessGroup, after[L_MAILLIST], after[L_LIST_NFSGROUP]))
1169         return;
1170
1171       if (ProcessGroup)
1172         {
1173           if (ProcessAce(ldap_handle, dn_path, after[L_NAME], "LIST", 1, 
1174                          &ProcessGroup, after[L_MAILLIST], 
1175                          after[L_LIST_NFSGROUP]))
1176             return;
1177         }
1178
1179       if (make_new_group(ldap_handle, dn_path, list_id, after[L_NAME], 
1180                          group_ou, group_membership, security_flag, 
1181                          updateGroup, after[L_MAILLIST], 
1182                          after[L_LIST_NFSGROUP]))
1183         {
1184           moira_disconnect();
1185           return;
1186         }
1187     
1188       if (atoi(after[L_ACTIVE]))
1189         {
1190           populate_group(ldap_handle, dn_path, after[L_NAME], group_ou, 
1191                          group_membership, security_flag, list_id, 1);
1192         }
1193
1194       moira_disconnect();
1195     }
1196   return;
1197 }
1198
1199 #define LM_EXTRA_ACTIVE   (LM_END)
1200 #define LM_EXTRA_PUBLIC   (LM_END+1)
1201 #define LM_EXTRA_HIDDEN   (LM_END+2)
1202 #define LM_EXTRA_MAILLIST (LM_END+3)
1203 #define LM_EXTRA_GROUP    (LM_END+4)
1204 #define LM_EXTRA_GID      (LM_END+5)
1205 #define LM_EXTRA_NFSGROUP (LM_END+6)
1206 #define LMN_LIST_ID       (LM_END+7)
1207 #define LM_LIST_ID        (LM_END+8)
1208 #define LM_USER_ID        (LM_END+9)
1209 #define LM_EXTRA_END      (LM_END+10)
1210
1211 void do_member(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
1212                char **before, int beforec, char **after, int afterc)
1213 {
1214   LK_ENTRY *group_base;
1215   int group_count;
1216   char  filter[128];
1217   char *attr_array[3];
1218   char  group_name[128];
1219   char  user_name[128];
1220   char  user_type[128];
1221   char  moira_list_id[32];
1222   char  moira_user_id[32];
1223   char  group_membership[1];
1224   char  group_ou[256];
1225   char  machine_ou[256];
1226   char  member[256];
1227   char  *args[16];
1228   char  **ptr;
1229   char  *av[7];
1230   char  *call_args[7];
1231   char  *pUserOu;
1232   char  *s;
1233   char  NewMachineName[1024];
1234   int   security_flag;
1235   int   rc;
1236   int   ProcessGroup;
1237   char  *save_argv[U_END];
1238
1239   pUserOu = NULL;
1240   ptr = NULL;
1241   memset(moira_list_id, '\0', sizeof(moira_list_id));
1242   memset(moira_user_id, '\0', sizeof(moira_user_id));
1243
1244   if (afterc)
1245     {
1246       if (afterc < LM_EXTRA_GID)
1247         return;
1248
1249       if (!atoi(after[LM_EXTRA_ACTIVE]))
1250         {
1251           com_err(whoami, 0, 
1252                   "Unable to add %s to group %s : group not active", 
1253                   after[2], after[0]);
1254           return;
1255         }
1256
1257       ptr = after;
1258
1259       if (!strcasecmp(ptr[LM_TYPE], "LIST"))
1260         return;
1261
1262       strcpy(user_name, after[LM_MEMBER]);
1263       strcpy(group_name, after[LM_LIST]);
1264       strcpy(user_type, after[LM_TYPE]);
1265
1266       if (!strcasecmp(ptr[LM_TYPE], "MACHINE"))
1267         {
1268           if (afterc > LM_EXTRA_GROUP)
1269             {
1270               strcpy(moira_list_id, after[LMN_LIST_ID]);
1271               strcpy(moira_user_id, after[LM_LIST_ID]);
1272             }
1273         }
1274       else if (!strcasecmp(ptr[LM_TYPE], "USER"))
1275         {
1276           if (afterc > LMN_LIST_ID)
1277             {
1278               strcpy(moira_list_id, after[LM_LIST_ID]);
1279               strcpy(moira_user_id, after[LM_USER_ID]);
1280             }
1281         }
1282       else
1283         {
1284           if (afterc > LM_EXTRA_GID)
1285             strcpy(moira_list_id, after[LMN_LIST_ID]);
1286         }
1287     }
1288   else if (beforec)
1289     {
1290       if (beforec < LM_EXTRA_GID)
1291         return;
1292       if (!atoi(before[LM_EXTRA_ACTIVE]))
1293         {
1294           com_err(whoami, 0, 
1295                   "Unable to remove %s from group %s : group not active", 
1296                   before[2], before[0]);
1297           return;
1298         }
1299
1300       ptr = before;
1301
1302       if (!strcasecmp(ptr[LM_TYPE], "LIST"))
1303         return;
1304
1305       strcpy(user_name, before[LM_MEMBER]);
1306       strcpy(group_name, before[LM_LIST]);
1307       strcpy(user_type, before[LM_TYPE]);
1308
1309       if (!strcasecmp(ptr[LM_TYPE], "MACHINE"))
1310         {
1311           if (beforec > LM_EXTRA_GROUP)
1312             {
1313               strcpy(moira_list_id, before[LMN_LIST_ID]);
1314               strcpy(moira_user_id, before[LM_LIST_ID]);
1315             }
1316         }
1317       else if (!strcasecmp(ptr[LM_TYPE], "USER"))
1318         {
1319           if (beforec > LMN_LIST_ID)
1320             {
1321               strcpy(moira_list_id, before[LM_LIST_ID]);
1322               strcpy(moira_user_id, before[LM_USER_ID]);
1323             }
1324         }
1325       else
1326         {
1327           if (beforec > LM_EXTRA_GID)
1328             strcpy(moira_list_id, before[LMN_LIST_ID]);
1329         }
1330     }
1331
1332   if (ptr == NULL)
1333     {
1334       com_err(whoami, 0, 
1335               "Unable to process group : beforec = %d, afterc = %d", 
1336               beforec, afterc);
1337       return;
1338     }
1339
1340   args[L_NAME] = ptr[LM_LIST];
1341   args[L_ACTIVE] = ptr[LM_EXTRA_ACTIVE];
1342   args[L_PUBLIC] = ptr[LM_EXTRA_PUBLIC];
1343   args[L_HIDDEN] = ptr[LM_EXTRA_HIDDEN];
1344   args[L_MAILLIST] = ptr[LM_EXTRA_MAILLIST];
1345   args[L_GROUP] = ptr[LM_EXTRA_GROUP];
1346   args[L_GID] = ptr[LM_EXTRA_GID];
1347
1348   security_flag = 0;
1349   memset(group_ou, '\0', sizeof(group_ou));
1350   get_group_membership(group_membership, group_ou, &security_flag, args);
1351
1352   if (strlen(group_ou) == 0)
1353     {
1354       com_err(whoami, 0, "Unable to find the group OU for group %s", 
1355               group_name);
1356       return;
1357     }
1358
1359   if (rc = process_group(ldap_handle, dn_path, moira_list_id, group_name, 
1360                          group_ou, group_membership, security_flag, 
1361                          CHECK_GROUPS, args[L_MAILLIST],
1362                          args[L_LIST_NFSGROUP]))
1363     {
1364       if (rc != AD_NO_GROUPS_FOUND)
1365         {
1366           if (rc = process_group(ldap_handle, dn_path, moira_list_id, 
1367                                  group_name, group_ou, group_membership, 
1368                                  security_flag, CLEANUP_GROUPS,
1369                                  args[L_MAILLIST], args[L_LIST_NFSGROUP]))
1370             {
1371               if (rc != AD_NO_GROUPS_FOUND)
1372                 {
1373                   if (afterc)
1374                     com_err(whoami, 0, "Unable to add %s to group %s - " 
1375                             "unable to process group", user_name, group_name);
1376                   else
1377                     com_err(whoami, 0, "Unable to remove %s from group %s - "
1378                             "unable to process group", user_name, group_name);
1379                   return;
1380                 }
1381             }
1382         }
1383     }
1384
1385   if (rc == AD_NO_GROUPS_FOUND)
1386     {
1387       if (rc = moira_connect())
1388         {
1389           critical_alert("Ldap incremental",
1390                          "Error contacting Moira server : %s",
1391                          error_message(rc));
1392           return;
1393         }
1394       
1395       com_err(whoami, 0, "creating group %s", group_name);
1396       ProcessGroup = 0;
1397
1398       if (ProcessAce(ldap_handle, dn_path, ptr[LM_LIST], "LIST", 0, 
1399                      &ProcessGroup, ptr[LM_EXTRA_MAILLIST],
1400                      ptr[LM_EXTRA_NFSGROUP]))
1401         return;
1402
1403       if (ProcessGroup)
1404         {
1405           if (ProcessAce(ldap_handle, dn_path, ptr[LM_LIST], "LIST", 1, 
1406                          &ProcessGroup, ptr[LM_EXTRA_MAILLIST],
1407                          ptr[LM_EXTRA_NFSGROUP]))
1408             return;
1409         }
1410
1411       if (make_new_group(ldap_handle, dn_path, moira_list_id, ptr[LM_LIST], 
1412                          group_ou, group_membership, security_flag, 0,
1413                          ptr[LM_EXTRA_MAILLIST], ptr[LM_EXTRA_NFSGROUP]))
1414         {
1415           moira_disconnect();
1416           return;
1417         }
1418     
1419       if (atoi(ptr[LM_EXTRA_ACTIVE]))
1420         {
1421           populate_group(ldap_handle, dn_path, ptr[LM_LIST], group_ou, 
1422                          group_membership, security_flag, moira_list_id, 1);
1423         }
1424
1425       moira_disconnect();
1426     }
1427
1428   rc = 0;
1429
1430   if (beforec)
1431     {
1432       com_err(whoami, 0, "removing user %s from list %s", user_name, 
1433               group_name);
1434       pUserOu = user_ou;
1435  
1436       if (!strcasecmp(ptr[LM_TYPE], "MACHINE"))
1437         {
1438           if (!ProcessMachineContainer)
1439             {
1440               com_err(whoami, 0, "Process machines and containers disabled, "
1441                       "skipping");
1442               return;
1443             }
1444
1445           memset(machine_ou, '\0', sizeof(machine_ou));
1446           memset(NewMachineName, '\0', sizeof(NewMachineName));
1447           if (get_machine_ou(ldap_handle, dn_path, ptr[LM_MEMBER], 
1448                              machine_ou, NewMachineName))
1449             return;
1450           if (ptr[LM_MEMBER] != NULL)     
1451             free(ptr[LM_MEMBER]);
1452           ptr[LM_MEMBER] = strdup(NewMachineName);
1453           pUserOu = machine_ou;
1454         }
1455
1456       if (!strcasecmp(ptr[LM_TYPE], "STRING"))
1457         {
1458           strcpy(member, ptr[LM_MEMBER]);
1459
1460           if (Exchange) 
1461             {
1462               if((s = strchr(member, '@')) == (char *) NULL)
1463                 { 
1464                   strcat(member, "@mit.edu");
1465                   
1466                   if (ptr[LM_MEMBER] != NULL)
1467                     free(ptr[LM_MEMBER]);
1468                   ptr[LM_MEMBER] = strdup(member);
1469                 }
1470           
1471               if(!strncasecmp(&member[strlen(member) - 6], ".LOCAL", 6)) 
1472                 {
1473                   s = strrchr(member, '.');
1474                   *s = '\0';
1475                   strcat(s, ".mit.edu");
1476                   
1477                   if (ptr[LM_MEMBER] != NULL)
1478                     free(ptr[LM_MEMBER]);
1479                   ptr[LM_MEMBER] = strdup(member);
1480                 }
1481             }
1482
1483           if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], 
1484                              contact_ou))
1485                 return;
1486
1487           pUserOu = contact_ou;
1488         }
1489       else if (!strcasecmp(ptr[LM_TYPE], "KERBEROS"))
1490         {
1491           if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], 
1492                              kerberos_ou))
1493             return;
1494
1495           pUserOu = kerberos_ou;
1496         }
1497
1498       if (rc = moira_connect()) {
1499         critical_alert("Ldap incremental",
1500                        "Error contacting Moira server : %s",
1501                        error_message(rc));              
1502         return;
1503       }
1504       
1505       if (rc = populate_group(ldap_handle, dn_path, group_name,
1506                               group_ou, group_membership, 
1507                               security_flag, moira_list_id, 0))
1508         com_err(whoami, 0, "Unable to remove %s from group %s", user_name, 
1509                 group_name);
1510       
1511       moira_disconnect();
1512
1513       if (rc = member_remove(ldap_handle, dn_path, group_name,
1514                              group_ou, group_membership, 
1515                              escape_string(ptr[LM_MEMBER]),
1516                              pUserOu, moira_list_id))
1517         com_err(whoami, 0, "Unable to remove %s from group %s", user_name,
1518                 group_name);
1519       
1520       return;
1521     }
1522   
1523   com_err(whoami, 0, "Adding %s to list %s", user_name, group_name);
1524   pUserOu = user_ou;
1525   
1526   if (!strcasecmp(ptr[LM_TYPE], "MACHINE"))
1527     {
1528       memset(machine_ou, '\0', sizeof(machine_ou));
1529       memset(NewMachineName, '\0', sizeof(NewMachineName));
1530
1531       if (get_machine_ou(ldap_handle, dn_path, ptr[LM_MEMBER], machine_ou, 
1532                          NewMachineName))
1533         return;
1534
1535       if (ptr[LM_MEMBER] != NULL)
1536         free(ptr[LM_MEMBER]);
1537
1538       ptr[LM_MEMBER] = strdup(NewMachineName);
1539       pUserOu = machine_ou;
1540     }
1541   else if (!strcasecmp(ptr[LM_TYPE], "STRING"))
1542     {
1543       strcpy(member, ptr[LM_MEMBER]);
1544
1545       if (Exchange) 
1546         {
1547           if((s = strchr(member, '@')) == (char *) NULL)
1548             { 
1549               strcat(member, "@mit.edu");
1550               
1551               if (ptr[LM_MEMBER] != NULL)
1552                 free(ptr[LM_MEMBER]);
1553               ptr[LM_MEMBER] = strdup(member);
1554             }
1555           
1556           if(!strncasecmp(&member[strlen(member) - 6], ".LOCAL", 6)) 
1557             {
1558               s = strrchr(member, '.');
1559               *s = '\0';
1560               strcat(s, ".mit.edu");
1561               
1562               if (ptr[LM_MEMBER] != NULL)
1563                 free(ptr[LM_MEMBER]);
1564               ptr[LM_MEMBER] = strdup(member);
1565             }
1566         }
1567       
1568       if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], 
1569                          contact_ou))
1570         return;
1571
1572       pUserOu = contact_ou;
1573     }
1574   else if (!strcasecmp(ptr[LM_TYPE], "KERBEROS"))
1575     {
1576       if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], 
1577                          kerberos_ou))
1578         return;
1579
1580       pUserOu = kerberos_ou;
1581     }
1582   else if (!strcasecmp(ptr[LM_TYPE], "USER"))
1583     {
1584       if ((rc = check_user(ldap_handle, dn_path, ptr[LM_MEMBER], 
1585                            moira_user_id)) == AD_NO_USER_FOUND)
1586         {
1587           if (rc = moira_connect())
1588             {
1589               critical_alert("Ldap incremental", 
1590                              "Error connection to Moira : %s",
1591                              error_message(rc));
1592               return;
1593             }
1594
1595           com_err(whoami, 0, "creating user %s", ptr[LM_MEMBER]);
1596           av[0] = ptr[LM_MEMBER];
1597           call_args[0] = (char *)ldap_handle;
1598           call_args[1] = dn_path;
1599           call_args[2] = moira_user_id;
1600           call_args[3] = NULL;
1601           
1602           callback_rc = 0;
1603
1604           if (Exchange)
1605             {
1606               group_count = 0;
1607               group_base = NULL;
1608           
1609               sprintf(filter, "(&(objectClass=group)(cn=%s))", ptr[LM_MEMBER]);
1610               attr_array[0] = "cn";
1611               attr_array[1] = NULL;
1612               if ((rc = linklist_build(ldap_handle, dn_path, filter, 
1613                                        attr_array, &group_base, &group_count,
1614                                        LDAP_SCOPE_SUBTREE)) != 0)
1615                 {
1616                   com_err(whoami, 0, "Unable to process user %s : %s",
1617                           ptr[LM_MEMBER], ldap_err2string(rc));
1618                   return;
1619                 }
1620               
1621               if (group_count)
1622                 {
1623                   com_err(whoami, 0, "Object already exists with name %s",
1624                           ptr[LM_MEMBER]);
1625                   return;
1626                 }
1627           
1628               linklist_free(group_base);
1629               group_count = 0;
1630               group_base = NULL;
1631             }
1632
1633           if (rc = mr_query("get_user_account_by_login", 1, av, 
1634                             save_query_info, save_argv))
1635             {
1636               moira_disconnect();
1637               com_err(whoami, 0, "Unable to create user %s : %s",
1638                       ptr[LM_MEMBER], error_message(rc));
1639               return;
1640             }
1641         
1642           if (rc = user_create(U_END, save_argv, call_args)) 
1643             {
1644               moira_disconnect();
1645               com_err(whoami, 0, "Unable to create user %s", ptr[LM_MEMBER]);
1646               return;
1647             }
1648
1649           if (callback_rc)
1650             {
1651               moira_disconnect();
1652               com_err(whoami, 0, "Unable to create user %s", ptr[LM_MEMBER]);
1653               return;
1654             }
1655         }
1656       else
1657         {
1658           if (rc != 0)
1659             return;
1660         }
1661       pUserOu = user_ou;
1662     }
1663
1664   if (rc = moira_connect()) {
1665     critical_alert("Ldap incremental",
1666                    "Error contacting Moira server : %s",
1667                    error_message(rc));              
1668     return;
1669   }
1670
1671   if (rc = populate_group(ldap_handle, dn_path, group_name,
1672                           group_ou, group_membership, security_flag,
1673                           moira_list_id, 0))
1674     com_err(whoami, 0, "Unable to add %s to group %s", user_name, 
1675             group_name);
1676   
1677   moira_disconnect();
1678
1679   if (rc = member_add(ldap_handle, dn_path, group_name,
1680                       group_ou, group_membership, 
1681                       escape_string(ptr[LM_MEMBER]),
1682                       pUserOu, moira_list_id))
1683     com_err(whoami, 0, "Unable to add %s to group %s", user_name, group_name);
1684
1685   return;
1686 }
1687
1688 #define U_USER_ID    10
1689 #define U_HOMEDIR    11
1690 #define U_PROFILEDIR 12
1691 #define U_POTYPE     13
1692
1693 void do_user(LDAP *ldap_handle, char *dn_path, char *ldap_hostname, 
1694              char **before, int beforec, char **after, 
1695              int afterc)
1696 {
1697   LK_ENTRY *group_base;
1698   int   group_count;
1699   char  filter[128];
1700   char  *attr_array[3];
1701   int   rc;
1702   char  *av[7];
1703   char  after_user_id[32];
1704   char  before_user_id[32];
1705   char  *call_args[7];
1706   char  *save_argv[U_END];
1707
1708   if ((beforec == 0) && (afterc == 0))
1709     return;
1710
1711   memset(after_user_id, '\0', sizeof(after_user_id));
1712   memset(before_user_id, '\0', sizeof(before_user_id));
1713
1714   if (beforec > U_USER_ID)
1715     strcpy(before_user_id, before[U_USER_ID]);
1716
1717   if (afterc > U_USER_ID)
1718     strcpy(after_user_id, after[U_USER_ID]);
1719
1720   if ((beforec == 0) && (afterc == 0)) /*this case should never happen */
1721     return;
1722
1723   if ((beforec == 0) && (afterc != 0)) 
1724     {
1725       /*this case only happens when the account*/
1726       /*account is first created but not usable*/
1727
1728       com_err(whoami, 0, "Unable to process user %s because the user account "
1729               "is not yet usable", after[U_NAME]);
1730       return;
1731     }
1732
1733   /*this case only happens when the account is expunged */
1734
1735   if ((beforec != 0) && (afterc == 0)) 
1736     {                                 
1737       if (atoi(before[U_STATE]) == 0)
1738         {
1739           com_err(whoami, 0, "expunging user %s from directory", 
1740                   before[U_NAME]);
1741           user_delete(ldap_handle, dn_path, before[U_NAME], before_user_id);
1742         }
1743       else
1744         {
1745           com_err(whoami, 0, "Unable to process because user %s has been "
1746                   "previously expungeded", before[U_NAME]);
1747         }
1748       return;
1749     }
1750
1751   /*process anything that gets here*/
1752
1753   if ((rc = check_user(ldap_handle, dn_path, before[U_NAME], 
1754                        before_user_id)) == AD_NO_USER_FOUND)
1755     {
1756       if (!check_string(after[U_NAME]))
1757         return;
1758
1759       if (rc = moira_connect())
1760         {
1761           critical_alert("Ldap incremental", 
1762                          "Error connection to Moira : %s",
1763                          error_message(rc));
1764           return;
1765         }
1766
1767       com_err(whoami, 0, "creating user %s", after[U_NAME]);
1768       
1769       av[0] = after[U_NAME];
1770       call_args[0] = (char *)ldap_handle;
1771       call_args[1] = dn_path;
1772       call_args[2] = after_user_id;
1773       call_args[3] = NULL;
1774       callback_rc = 0;
1775
1776       if (Exchange) 
1777         {
1778           group_count = 0;
1779           group_base = NULL;
1780           
1781           sprintf(filter, "(&(objectClass=group)(cn=%s))", after[U_NAME]);
1782           attr_array[0] = "cn";
1783           attr_array[1] = NULL;
1784           
1785           if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
1786                                    &group_base, &group_count,
1787                                    LDAP_SCOPE_SUBTREE)) != 0)
1788             {
1789               com_err(whoami, 0, "Unable to process user %s : %s",
1790                       after[U_NAME], ldap_err2string(rc));
1791               return;
1792             }
1793           
1794           if (group_count >= 1)
1795             {
1796               com_err(whoami, 0, "Object already exists with name %s",
1797                       after[U_NAME]);
1798               return;
1799             }
1800       
1801           linklist_free(group_base);
1802           group_count = 0;
1803           group_base = NULL;
1804         }
1805
1806       if (rc = mr_query("get_user_account_by_login", 1, av,
1807                         save_query_info, save_argv))
1808         {
1809           moira_disconnect();
1810           com_err(whoami, 0, "Unable to create user %s : %s",
1811                   after[U_NAME], error_message(rc));
1812           return;
1813         }
1814
1815       if (rc = user_create(U_END, save_argv, call_args)) 
1816         {
1817           com_err(whoami, 0, "Unable to create user %s : %s",
1818                   after[U_NAME], error_message(rc));
1819           return;
1820         }
1821       
1822       if (callback_rc)
1823         {
1824           moira_disconnect();
1825           com_err(whoami, 0, "Unable to create user %s", after[U_NAME]);
1826           return;
1827         }
1828
1829       return;
1830     }
1831   else
1832     {
1833       if (rc != 0)
1834         return;
1835     }
1836
1837   if (strcmp(before[U_NAME], after[U_NAME]))
1838     {
1839       if ((check_string(before[U_NAME])) && (check_string(after[U_NAME])))
1840         {
1841           com_err(whoami, 0, "changing user %s to %s", 
1842                   before[U_NAME], after[U_NAME]);
1843
1844           if ((rc = user_rename(ldap_handle, dn_path, before[U_NAME], 
1845                                 after[U_NAME])) != LDAP_SUCCESS)
1846             {
1847               return;
1848             }
1849         }
1850     }
1851
1852   com_err(whoami, 0, "updating user %s information", after[U_NAME]);
1853
1854   rc = user_update(ldap_handle, dn_path, after[U_NAME],
1855                    after[U_UID], after[U_MITID], 
1856                    after_user_id, atoi(after[U_STATE]),
1857                    after[U_HOMEDIR], after[U_PROFILEDIR],
1858                    after[U_FIRST], after[U_MIDDLE], after[U_LAST], 
1859                    after[U_SHELL], after[U_CLASS]);
1860
1861   return;
1862 }
1863
1864 int construct_newvalues(LK_ENTRY *linklist_base, int modvalue_count, 
1865                         char *oldValue, char *newValue,
1866                         char ***modvalues, int type)
1867 {
1868   LK_ENTRY    *linklist_ptr;
1869   int         i;
1870   char        *cPtr;
1871   
1872   if (((*modvalues) = calloc(1, 
1873                              (modvalue_count + 1) * sizeof(char *))) == NULL)
1874     {
1875       return(1);
1876     }
1877
1878   for (i = 0; i < (modvalue_count + 1); i++)
1879     (*modvalues)[i] = NULL;
1880
1881   if (modvalue_count != 0)
1882     {
1883       linklist_ptr = linklist_base;
1884       for (i = 0; i < modvalue_count; i++)
1885         {
1886           if ((oldValue != NULL) && (newValue != NULL))
1887             {
1888               if ((cPtr = (char *)strstr(linklist_ptr->value, oldValue))
1889                   != (char *)NULL)
1890                 {
1891                   if (type == REPLACE)
1892                     {
1893                       if (((*modvalues)[i] = calloc(1, strlen(newValue) + 1))
1894                           == NULL)
1895                         return(1);
1896                       memset((*modvalues)[i], '\0', strlen(newValue) + 1);
1897                       strcpy((*modvalues)[i], newValue);
1898                     }
1899                   else
1900                     {
1901                       if (((*modvalues)[i] = calloc(1, 
1902                                         (int)(cPtr - linklist_ptr->value) + 
1903                                                (linklist_ptr->length - 
1904                                                strlen(oldValue)) + 
1905                                                strlen(newValue) + 1)) == NULL)
1906                         return(1);
1907                       memset((*modvalues)[i], '\0', 
1908                              (int)(cPtr - linklist_ptr->value) + 
1909                              (linklist_ptr->length - strlen(oldValue)) + 
1910                              strlen(newValue) + 1);
1911                       memcpy((*modvalues)[i], linklist_ptr->value, 
1912                              (int)(cPtr - linklist_ptr->value));
1913                       strcat((*modvalues)[i], newValue);
1914                       strcat((*modvalues)[i], 
1915                              &linklist_ptr->value[(int)(cPtr - 
1916                                      linklist_ptr->value) + strlen(oldValue)]);
1917                     }
1918                 }
1919               else
1920                 {
1921                   (*modvalues)[i] = calloc(1, linklist_ptr->length + 1);
1922                   memset((*modvalues)[i], '\0', linklist_ptr->length + 1);
1923                   memcpy((*modvalues)[i], linklist_ptr->value,
1924                          linklist_ptr->length);
1925                 }
1926             }
1927         else
1928             {
1929               (*modvalues)[i] = calloc(1, linklist_ptr->length + 1);
1930               memset((*modvalues)[i], '\0', linklist_ptr->length + 1);
1931               memcpy((*modvalues)[i], linklist_ptr->value,
1932                      linklist_ptr->length);
1933             }
1934           linklist_ptr = linklist_ptr->next;
1935         }
1936       (*modvalues)[i] = NULL;
1937     }
1938   return(0);
1939 }
1940
1941
1942 int linklist_build(LDAP *ldap_handle, char *dn_path, char *search_exp, 
1943                    char **attr_array, LK_ENTRY **linklist_base,
1944                    int *linklist_count, unsigned long ScopeType)
1945 {
1946   ULONG       rc;
1947   LDAPMessage *ldap_entry;
1948
1949   rc = 0;
1950   ldap_entry = NULL;
1951   (*linklist_base) = NULL;
1952   (*linklist_count) = 0;
1953
1954   if ((rc = ldap_search_s(ldap_handle, dn_path, ScopeType, 
1955                           search_exp, attr_array, 0, 
1956                           &ldap_entry)) != LDAP_SUCCESS)
1957       {
1958         if (rc != LDAP_SIZELIMIT_EXCEEDED)
1959           return(0);
1960       }
1961
1962   rc = retrieve_entries(ldap_handle, ldap_entry, linklist_base, 
1963                         linklist_count);
1964
1965   ldap_msgfree(ldap_entry);
1966   return(rc);
1967 }
1968
1969 int retrieve_entries(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
1970                      LK_ENTRY **linklist_base, int *linklist_count)
1971 {
1972   char        distinguished_name[1024];
1973   LK_ENTRY    *linklist_ptr;
1974   int         rc;
1975
1976   if ((ldap_entry = ldap_first_entry(ldap_handle, ldap_entry)) == NULL)
1977     return(0);
1978   
1979   memset(distinguished_name, '\0', sizeof(distinguished_name));
1980   get_distinguished_name(ldap_handle, ldap_entry, distinguished_name);
1981
1982   if ((rc = retrieve_attributes(ldap_handle, ldap_entry, distinguished_name,
1983                                 linklist_base)) != 0)
1984     return(rc);
1985
1986   while ((ldap_entry = ldap_next_entry(ldap_handle, ldap_entry)) != NULL)
1987     {
1988       memset(distinguished_name, '\0', sizeof(distinguished_name));
1989       get_distinguished_name(ldap_handle, ldap_entry, distinguished_name);
1990       
1991       if ((rc = retrieve_attributes(ldap_handle, ldap_entry, 
1992                                     distinguished_name, linklist_base)) != 0)
1993         return(rc);
1994     }
1995
1996   linklist_ptr = (*linklist_base);
1997   (*linklist_count) = 0;
1998
1999   while (linklist_ptr != NULL)
2000     {
2001       ++(*linklist_count);
2002       linklist_ptr = linklist_ptr->next;
2003     }
2004
2005   return(0);
2006 }
2007
2008 int retrieve_attributes(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
2009                         char *distinguished_name, LK_ENTRY **linklist_current)
2010 {
2011   char        *Attribute;
2012   BerElement  *ptr;
2013
2014   ptr = NULL;
2015
2016   if ((Attribute = ldap_first_attribute(ldap_handle, ldap_entry, 
2017                                         &ptr)) != NULL)
2018     {
2019       retrieve_values(ldap_handle, ldap_entry, Attribute, distinguished_name,
2020                       linklist_current);
2021       ldap_memfree(Attribute);
2022       while ((Attribute = ldap_next_attribute(ldap_handle, ldap_entry, 
2023                                               ptr)) != NULL)
2024         {
2025           retrieve_values(ldap_handle, ldap_entry, Attribute,
2026                           distinguished_name, linklist_current);
2027           ldap_memfree(Attribute);
2028         }
2029     }
2030
2031   ldap_ber_free(ptr, 0);
2032
2033   return(0);
2034 }
2035
2036 int retrieve_values(LDAP *ldap_handle, LDAPMessage *ldap_entry,
2037                     char *Attribute, char *distinguished_name,
2038                     LK_ENTRY **linklist_current)
2039 {
2040   char        **str_value;
2041   char        temp[256];
2042   void        **Ptr;
2043   int         use_bervalue;
2044   LK_ENTRY    *linklist_previous;
2045   LDAP_BERVAL **ber_value;
2046   DWORD       ber_length;
2047
2048 #ifdef LDAP_DEBUG
2049   SID         *sid;
2050   GUID        *guid;
2051   int         i;
2052   int         intValue;
2053   DWORD       *subauth;
2054   SID_IDENTIFIER_AUTHORITY    *sid_auth;
2055   unsigned char   *subauth_count;
2056 #endif /*LDAP_BEGUG*/
2057
2058   use_bervalue = 0;
2059   memset(temp, '\0', sizeof(temp));
2060
2061   if ((!strcmp(Attribute, "objectSid")) ||
2062       (!strcmp(Attribute, "objectGUID")))
2063     use_bervalue = 1;
2064   
2065   if (use_bervalue)
2066     {
2067       ber_value = ldap_get_values_len(ldap_handle, ldap_entry, Attribute);
2068       Ptr = (void **)ber_value;
2069       str_value = NULL;
2070     }
2071   else
2072     {
2073       str_value = ldap_get_values(ldap_handle, ldap_entry, Attribute);
2074       Ptr = (void **)str_value;
2075       ber_value = NULL;
2076     }
2077
2078   if (Ptr != NULL)
2079     {
2080       for (; *Ptr; Ptr++) 
2081         {
2082           if ((linklist_previous = calloc(1, sizeof(LK_ENTRY))) == NULL)
2083             return(1);
2084
2085           memset(linklist_previous, '\0', sizeof(LK_ENTRY));
2086           linklist_previous->next = (*linklist_current);
2087           (*linklist_current) = linklist_previous;
2088           
2089           if (((*linklist_current)->attribute = calloc(1, 
2090                                               strlen(Attribute) + 1)) == NULL)
2091             return(1);
2092
2093           memset((*linklist_current)->attribute, '\0', strlen(Attribute) + 1);
2094           strcpy((*linklist_current)->attribute, Attribute);
2095
2096           if (use_bervalue)
2097             {
2098               ber_length = (*(LDAP_BERVAL **)Ptr)->bv_len;
2099
2100               if (((*linklist_current)->value = calloc(1, ber_length)) == NULL)
2101                 return(1);
2102
2103               memset((*linklist_current)->value, '\0', ber_length);
2104               memcpy((*linklist_current)->value, 
2105                      (*(LDAP_BERVAL **)Ptr)->bv_val, ber_length);
2106               (*linklist_current)->length = ber_length;
2107             }
2108           else
2109             {
2110               if (((*linklist_current)->value = calloc(1, 
2111                                                     strlen(*Ptr) + 1)) == NULL)
2112                 return(1);
2113
2114               memset((*linklist_current)->value, '\0', strlen(*Ptr) + 1);
2115               (*linklist_current)->length = strlen(*Ptr);
2116               strcpy((*linklist_current)->value, *Ptr);
2117             }
2118
2119           (*linklist_current)->ber_value = use_bervalue;
2120
2121           if (((*linklist_current)->dn = calloc(1, 
2122                                       strlen(distinguished_name) + 1)) == NULL)
2123             return(1);
2124
2125           memset((*linklist_current)->dn, '\0', 
2126                  strlen(distinguished_name) + 1);
2127           strcpy((*linklist_current)->dn, distinguished_name);
2128
2129 #ifdef LDAP_DEBUG
2130           if (!strcmp(Attribute, "objectGUID"))
2131             {
2132               guid = (GUID *)((*linklist_current)->value);
2133               sprintf(temp, 
2134                       "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 
2135                       guid->Data1, guid->Data2, guid->Data3, 
2136                       guid->Data4[0], guid->Data4[1], guid->Data4[2], 
2137                       guid->Data4[3], guid->Data4[4], guid->Data4[5], 
2138                       guid->Data4[6], guid->Data4[7]);
2139               print_to_screen("     %20s : {%s}\n", Attribute, temp);
2140             }
2141           else if (!strcmp(Attribute, "objectSid"))
2142             {
2143               sid = (SID *)((*(LDAP_BERVAL **)Ptr)->bv_val);
2144
2145 #ifdef _WIN32
2146               print_to_screen("        Revision = %d\n", sid->Revision);
2147               print_to_screen("        SID Identifier Authority:\n");
2148               sid_auth = &sid->IdentifierAuthority;
2149               if (sid_auth->Value[0])
2150                 print_to_screen("            SECURITY_NULL_SID_AUTHORITY\n");
2151               else if (sid_auth->Value[1])
2152                 print_to_screen("            SECURITY_WORLD_SID_AUTHORITY\n");
2153               else if (sid_auth->Value[2])
2154                 print_to_screen("            SECURITY_LOCAL_SID_AUTHORITY\n");
2155               else if (sid_auth->Value[3])
2156                 print_to_screen("           SECURITY_CREATOR_SID_AUTHORITY\n");
2157               else if (sid_auth->Value[5])
2158                 print_to_screen("            SECURITY_NT_AUTHORITY\n");
2159               else
2160                 print_to_screen("            UNKNOWN SID AUTHORITY\n");
2161               subauth_count = GetSidSubAuthorityCount(sid);
2162               print_to_screen("        SidSubAuthorityCount = %d\n", 
2163                               *subauth_count);
2164               print_to_screen("        SidSubAuthority:\n");
2165               for (i = 0; i < *subauth_count; i++)
2166                 {
2167                   if ((subauth = GetSidSubAuthority(sid, i)) != NULL)
2168                     print_to_screen("            %u\n", *subauth);
2169                 }
2170 #endif
2171             }
2172           else if ((!memcmp(Attribute, "userAccountControl", 
2173                             strlen("userAccountControl"))) ||
2174                    (!memcmp(Attribute, "sAMAccountType", 
2175                             strlen("sAmAccountType"))))
2176             {
2177               intValue = atoi(*Ptr);
2178               print_to_screen("     %20s : %ld\n",Attribute, intValue);
2179
2180               if (!memcmp(Attribute, "userAccountControl", 
2181                           strlen("userAccountControl")))
2182                 {
2183                   if (intValue & UF_ACCOUNTDISABLE)
2184                     print_to_screen("     %20s :    %s\n", 
2185                                     "", "Account disabled");
2186                   else
2187                     print_to_screen("     %20s :    %s\n", 
2188                                     "", "Account active");
2189                   if (intValue & UF_HOMEDIR_REQUIRED)
2190                     print_to_screen("     %20s :    %s\n", 
2191                                     "", "Home directory required");
2192                   if (intValue & UF_LOCKOUT)
2193                     print_to_screen("     %20s :    %s\n", 
2194                                     "", "Account locked out");
2195                   if (intValue & UF_PASSWD_NOTREQD)
2196                     print_to_screen("     %20s :    %s\n", 
2197                                     "", "No password required");
2198                   if (intValue & UF_PASSWD_CANT_CHANGE)
2199                     print_to_screen("     %20s :    %s\n",
2200                                     "", "Cannot change password");
2201                   if (intValue & UF_TEMP_DUPLICATE_ACCOUNT)
2202                     print_to_screen("     %20s :    %s\n", 
2203                                     "", "Temp duplicate account");
2204                   if (intValue & UF_NORMAL_ACCOUNT)
2205                     print_to_screen("     %20s :    %s\n", 
2206                                     "", "Normal account");
2207                   if (intValue & UF_INTERDOMAIN_TRUST_ACCOUNT)
2208                     print_to_screen("     %20s :    %s\n", 
2209                                     "", "Interdomain trust account");
2210                   if (intValue & UF_WORKSTATION_TRUST_ACCOUNT)
2211                     print_to_screen("     %20s :    %s\n", 
2212                                     "", "Workstation trust account");
2213                   if (intValue & UF_SERVER_TRUST_ACCOUNT)
2214                     print_to_screen("     %20s :    %s\n", 
2215                                     "", "Server trust account");
2216                 }
2217             }
2218           else
2219             {
2220               print_to_screen("     %20s : %s\n",Attribute, *Ptr);
2221             }
2222 #endif /*LDAP_DEBUG*/
2223         }
2224
2225       if (str_value != NULL)
2226         ldap_value_free(str_value);
2227
2228       if (ber_value != NULL)
2229         ldap_value_free_len(ber_value);
2230     }
2231
2232   (*linklist_current) = linklist_previous;
2233
2234   return(0);
2235 }
2236
2237 int moira_connect(void)
2238 {
2239   long    rc;
2240   char    HostName[64];
2241
2242   if (!mr_connections++)
2243     {
2244
2245 #ifdef _WIN32
2246       memset(HostName, '\0', sizeof(HostName));
2247       strcpy(HostName, "ttsp");
2248       rc = mr_connect_cl(HostName, "ldap.incr", QUERY_VERSION, 1);
2249 #else
2250       struct utsname uts;
2251       uname(&uts);
2252       rc = mr_connect_cl(uts.nodename, "ldap.incr", QUERY_VERSION, 1);
2253 #endif /*WIN32*/
2254
2255       return rc;
2256     }
2257
2258   return 0;
2259 }
2260
2261 int check_winad(void)
2262 {
2263   int i;
2264   
2265   for (i = 0; file_exists(STOP_FILE); i++)
2266     {
2267       if (i > 30)
2268         {
2269           critical_alert("Ldap incremental",
2270                          "Ldap incremental failed (%s exists): %s",
2271                          STOP_FILE, tbl_buf);
2272           return(1);
2273         }
2274
2275       sleep(60);
2276     }
2277
2278   return(0);
2279 }
2280
2281 int moira_disconnect(void)
2282 {
2283
2284   if (!--mr_connections)
2285     {
2286       mr_disconnect();
2287     }
2288
2289   return 0;
2290 }
2291
2292 void get_distinguished_name(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
2293                             char *distinguished_name)
2294 {
2295   char    *CName;
2296   
2297   CName = ldap_get_dn(ldap_handle, ldap_entry);
2298
2299   if (CName == NULL)
2300     return;
2301
2302   strcpy(distinguished_name, CName);
2303   ldap_memfree(CName);
2304 }
2305
2306 int linklist_create_entry(char *attribute, char *value, 
2307                           LK_ENTRY **linklist_entry)
2308 {
2309   (*linklist_entry) = calloc(1, sizeof(LK_ENTRY));
2310
2311   if (!(*linklist_entry))
2312     {
2313       return(1);
2314     }
2315
2316   memset((*linklist_entry), '\0', sizeof(LK_ENTRY));
2317   (*linklist_entry)->attribute = calloc(1, strlen(attribute) + 1);
2318   memset((*linklist_entry)->attribute, '\0', strlen(attribute) + 1);
2319   strcpy((*linklist_entry)->attribute, attribute);
2320   (*linklist_entry)->value = calloc(1, strlen(value) + 1);
2321   memset((*linklist_entry)->value, '\0', strlen(value) + 1);
2322   strcpy((*linklist_entry)->value, value);
2323   (*linklist_entry)->length = strlen(value);
2324   (*linklist_entry)->next = NULL;
2325
2326   return(0);
2327 }
2328
2329 void print_to_screen(const char *fmt, ...)
2330 {
2331   va_list pvar;
2332
2333   va_start(pvar, fmt);
2334   vfprintf(stderr, fmt, pvar);
2335   fflush(stderr);
2336   va_end(pvar);
2337 }
2338
2339 int get_group_membership(char *group_membership, char *group_ou, 
2340                          int *security_flag, char **av)
2341 {
2342   int  maillist_flag;
2343   int  group_flag;
2344   
2345   maillist_flag = atoi(av[L_MAILLIST]);
2346   group_flag = atoi(av[L_GROUP]);
2347
2348   if (security_flag != NULL)
2349     (*security_flag) = 0;
2350   
2351   if ((maillist_flag) && (group_flag))
2352     {
2353       if (group_membership != NULL)
2354         group_membership[0] = 'B';
2355
2356       if (security_flag != NULL)
2357         (*security_flag) = 1;
2358
2359       if (group_ou != NULL)
2360         strcpy(group_ou, group_ou_both);
2361     }
2362   else if ((!maillist_flag) && (group_flag))
2363     {
2364       if (group_membership != NULL)
2365         group_membership[0] = 'S';
2366
2367       if (security_flag != NULL)
2368         (*security_flag) = 1;
2369
2370       if (group_ou != NULL)
2371         strcpy(group_ou, group_ou_security);
2372     }
2373   else if ((maillist_flag) && (!group_flag))
2374     {
2375       if (group_membership != NULL)
2376         group_membership[0] = 'D';
2377
2378       if (group_ou != NULL)
2379         strcpy(group_ou, group_ou_distribution);
2380     }
2381   else
2382     {
2383       if (group_membership != NULL)
2384         group_membership[0] = 'N';
2385
2386       if (group_ou != NULL)
2387         strcpy(group_ou, group_ou_neither);
2388     }
2389
2390   return(0);
2391 }
2392
2393 int group_rename(LDAP *ldap_handle, char *dn_path, 
2394                  char *before_group_name, char *before_group_membership, 
2395                  char *before_group_ou, int before_security_flag, 
2396                  char *before_desc, char *after_group_name, 
2397                  char *after_group_membership, char *after_group_ou, 
2398                  int after_security_flag, char *after_desc,
2399                  char *MoiraId, char *filter, char *maillist, char *nfsgroup)
2400 {
2401   LDAPMod   *mods[20];
2402   char      old_dn[512];
2403   char      new_dn[512];
2404   char      new_dn_path[512];
2405   char      sam_name[256];
2406   char      mail[256];
2407   char      mail_nickname[256];
2408   char      proxy_address[256];
2409   char      address_book[256];
2410   char      *attr_array[3];
2411   char      *mitMoiraId_v[] = {NULL, NULL};
2412   char      *name_v[] = {NULL, NULL};
2413   char      *samAccountName_v[] = {NULL, NULL};
2414   char      *groupTypeControl_v[] = {NULL, NULL};
2415   char      *mail_v[] = {NULL, NULL};
2416   char      *proxy_address_v[] = {NULL, NULL};
2417   char      *mail_nickname_v[] = {NULL, NULL};
2418   char      *report_to_originator_v[] = {NULL, NULL};
2419   char      *address_book_v[] = {NULL, NULL};
2420   char      *legacy_exchange_dn_v[] = {NULL, NULL};
2421   char      *null_v[] = {NULL, NULL};
2422   u_int     groupTypeControl;
2423   char      groupTypeControlStr[80];
2424   char      contact_mail[256];
2425   int       n;
2426   int       i;
2427   int       rc;
2428   LK_ENTRY  *group_base;
2429   int       group_count;
2430   int       MailDisabled = 0;
2431   char      search_filter[1024];
2432
2433   if(UseGroupUniversal)
2434     groupTypeControl = ADS_GROUP_TYPE_UNIVERSAL_GROUP;
2435   else
2436     groupTypeControl = ADS_GROUP_TYPE_GLOBAL_GROUP;
2437      
2438   if (!check_string(before_group_name))
2439     {
2440       com_err(whoami, 0, 
2441               "Unable to process invalid LDAP list name %s", 
2442               before_group_name);
2443       return(AD_INVALID_NAME);
2444     }
2445
2446   if (!check_string(after_group_name))
2447     {
2448       com_err(whoami, 0, 
2449               "Unable to process invalid LDAP list name %s", after_group_name);
2450       return(AD_INVALID_NAME);
2451     }
2452
2453   if (Exchange) 
2454     {
2455       if(atoi(maillist)) 
2456         {
2457           group_count = 0;
2458           group_base = NULL;
2459           
2460           sprintf(search_filter, "(&(objectClass=user)(cn=%s))", 
2461                   after_group_name);
2462           attr_array[0] = "cn";
2463           attr_array[1] = NULL;
2464
2465           if ((rc = linklist_build(ldap_handle, dn_path, search_filter, 
2466                                    attr_array, &group_base, &group_count,
2467                                    LDAP_SCOPE_SUBTREE)) != 0)
2468           {
2469             com_err(whoami, 0, "Unable to process group %s : %s",
2470                     after_group_name, ldap_err2string(rc));
2471             return(rc);
2472           }
2473           
2474           if (group_count)
2475             {
2476               com_err(whoami, 0, "Object already exists with name %s",
2477                       after_group_name);
2478               MailDisabled++;
2479             }
2480         
2481           linklist_free(group_base);
2482           group_base = NULL;
2483           group_count = 0;
2484         }
2485     }
2486
2487   group_count = 0;
2488   group_base = NULL;
2489
2490   if (rc = ad_get_group(ldap_handle, dn_path, before_group_name, 
2491                         before_group_membership, 
2492                         MoiraId, "samAccountName", &group_base, 
2493                         &group_count, filter))
2494     return(rc);
2495
2496   if (group_count == 0)
2497     {
2498       return(AD_NO_GROUPS_FOUND);
2499     }
2500
2501   if (group_count != 1)
2502     {
2503       com_err(whoami, 0, "Unable to process multiple groups with "
2504               "MoiraId = %s exist in the directory", MoiraId);
2505       return(AD_MULTIPLE_GROUPS_FOUND);
2506     }
2507
2508   strcpy(old_dn, group_base->dn);
2509
2510   linklist_free(group_base);
2511   group_base = NULL;
2512   group_count = 0;
2513   attr_array[0] = "sAMAccountName";
2514   attr_array[1] = NULL;
2515
2516   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
2517                            &group_base, &group_count, 
2518                            LDAP_SCOPE_SUBTREE)) != 0)
2519     {
2520       com_err(whoami, 0, "Unable to get list %s dn : %s",
2521               after_group_name, ldap_err2string(rc));
2522       return(rc);
2523     }
2524
2525   if (group_count != 1)
2526     {
2527       com_err(whoami, 0,
2528               "Unable to get sAMAccountName for group %s", 
2529               before_group_name);
2530       return(AD_LDAP_FAILURE);
2531     }
2532   
2533   strcpy(sam_name, group_base->value);
2534   linklist_free(group_base);
2535   group_base = NULL;
2536   group_count = 0;
2537   
2538   sprintf(new_dn_path, "%s,%s", after_group_ou, dn_path);
2539   sprintf(new_dn, "cn=%s", after_group_name);
2540   sprintf(mail, "%s@%s", after_group_name, lowercase(ldap_domain));
2541   sprintf(contact_mail, "%s@mit.edu", after_group_name); 
2542   sprintf(proxy_address, "SMTP:%s@%s", after_group_name, 
2543           lowercase(ldap_domain));
2544   sprintf(mail_nickname, "%s", after_group_name);
2545
2546   com_err(whoami, 0, "Old %s New %s,%s", old_dn, new_dn, new_dn_path);
2547
2548   if ((rc = ldap_rename_s(ldap_handle, old_dn, new_dn, new_dn_path,
2549                               TRUE, NULL, NULL)) != LDAP_SUCCESS)
2550     {
2551       com_err(whoami, 0, "Unable to rename list from %s to %s : %s",
2552               before_group_name, after_group_name, ldap_err2string(rc));
2553       return(rc);
2554     }
2555   
2556   name_v[0] = after_group_name;
2557
2558   if (!strncmp(&sam_name[strlen(sam_name) - strlen(group_suffix)], 
2559                group_suffix, strlen(group_suffix)))
2560     {
2561       sprintf(sam_name, "%s%s", after_group_name, group_suffix);
2562     }
2563   else
2564     {
2565       com_err(whoami, 0, 
2566               "Unable to rename list from %s to %s : sAMAccountName not found",
2567               before_group_name, after_group_name);
2568       return(rc);
2569     }
2570
2571   samAccountName_v[0] = sam_name;
2572
2573   if (after_security_flag)
2574     groupTypeControl |= ADS_GROUP_TYPE_SECURITY_ENABLED;
2575
2576   sprintf(groupTypeControlStr, "%ld", groupTypeControl);
2577   groupTypeControl_v[0] = groupTypeControlStr;
2578   mitMoiraId_v[0] = MoiraId;
2579
2580   sprintf(new_dn, "cn=%s,%s,%s", after_group_name, after_group_ou, dn_path);
2581   rc = attribute_update(ldap_handle, new_dn, after_desc, "description", 
2582                         after_group_name);
2583   n = 0;
2584   ADD_ATTR("samAccountName", samAccountName_v, LDAP_MOD_REPLACE);
2585   ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
2586   ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
2587   ADD_ATTR("groupType", groupTypeControl_v, LDAP_MOD_REPLACE);
2588
2589   if (Exchange)
2590     {
2591       if(atoi(maillist) && !MailDisabled && email_isvalid(mail)) 
2592         {
2593           mail_nickname_v[0] = mail_nickname;
2594           proxy_address_v[0] = proxy_address;
2595           mail_v[0] = mail;
2596           report_to_originator_v[0] = "TRUE";
2597
2598           ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_REPLACE);
2599           ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
2600           ADD_ATTR("proxyAddresses", proxy_address_v, LDAP_MOD_REPLACE);
2601           ADD_ATTR("reportToOriginator", report_to_originator_v, 
2602                    LDAP_MOD_REPLACE);
2603         } 
2604       else 
2605         {
2606           mail_nickname_v[0] = NULL;
2607           proxy_address_v[0] = NULL;
2608           mail_v[0] = NULL;
2609           legacy_exchange_dn_v[0] = NULL;
2610           address_book_v[0] = NULL;
2611           report_to_originator_v[0] = NULL;
2612
2613           ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_REPLACE);
2614           ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
2615           ADD_ATTR("proxyAddresses", proxy_address_v, LDAP_MOD_REPLACE);
2616           ADD_ATTR("legacyExchangeDN", legacy_exchange_dn_v, LDAP_MOD_REPLACE);
2617           ADD_ATTR("showInAddressBook", address_book_v, LDAP_MOD_REPLACE);
2618           ADD_ATTR("reportToOriginator", report_to_originator_v, 
2619                    LDAP_MOD_REPLACE);
2620         }
2621     }
2622   else
2623     {
2624       if(atoi(maillist) && email_isvalid(contact_mail)) 
2625         {
2626           mail_v[0] = contact_mail;
2627           ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
2628
2629           if(!ActiveDirectory)
2630             {
2631               null_v[0] = "/dev/null";
2632               ADD_ATTR("mailRoutingAddress", null_v, LDAP_MOD_REPLACE);
2633               ADD_ATTR("mitMoiraMail", mail_v, LDAP_MOD_REPLACE);
2634             }
2635         }
2636     }
2637
2638   mods[n] = NULL;
2639
2640   if ((rc = ldap_modify_s(ldap_handle, new_dn, mods)) != LDAP_SUCCESS)
2641     {
2642       com_err(whoami, 0, 
2643               "Unable to modify list data for %s after renaming: %s",
2644               after_group_name, ldap_err2string(rc));
2645     }
2646
2647   for (i = 0; i < n; i++)
2648     free(mods[i]);
2649
2650   return(rc);
2651 }
2652
2653 int group_create(int ac, char **av, void *ptr)
2654 {
2655   LDAPMod *mods[20];
2656   char new_dn[256];
2657   char group_ou[256];
2658   char new_group_name[256];
2659   char sam_group_name[256];
2660   char cn_group_name[256];
2661   char mail[256];
2662   char contact_mail[256];
2663   char mail_nickname[256];
2664   char proxy_address[256];
2665   char address_book[256];
2666   char *cn_v[] = {NULL, NULL};
2667   char *objectClass_v[] = {"top", "group", NULL};
2668   char *objectClass_ldap_v[] = {"top", "microsoftComTop", "securityPrincipal",
2669                                 "group", "mailRecipient", NULL};
2670   char info[256];
2671   char *samAccountName_v[] = {NULL, NULL};
2672   char *altSecurityIdentities_v[] = {NULL, NULL};
2673   char *member_v[] = {NULL, NULL};
2674   char *name_v[] = {NULL, NULL};
2675   char *desc_v[] = {NULL, NULL};
2676   char *info_v[] = {NULL, NULL};
2677   char *mitMoiraId_v[] = {NULL, NULL};
2678   char *mitMoiraPublic_v[] = {NULL, NULL};
2679   char *mitMoiraHidden_v[] = {NULL, NULL};
2680   char *mitMoiraActive_v[] = {NULL, NULL};
2681   char *mitMoiraNFSGroup_v[] = {NULL, NULL};
2682   char *groupTypeControl_v[] = {NULL, NULL};
2683   char *mail_v[] = {NULL, NULL};
2684   char *proxy_address_v[] = {NULL, NULL};
2685   char *mail_nickname_v[] = {NULL, NULL};
2686   char *report_to_originator_v[] = {NULL, NULL};
2687   char *address_book_v[] = {NULL, NULL};
2688   char *legacy_exchange_dn_v[] = {NULL, NULL};
2689   char *gidNumber_v[] = {NULL, NULL};
2690   char *null_v[] = {NULL, NULL};
2691   char groupTypeControlStr[80];
2692   char group_membership[1];
2693   int  i;
2694   int  security_flag;
2695   u_int groupTypeControl;
2696   int  n;
2697   int  rc;
2698   int  updateGroup;
2699   int  MailDisabled = 0;
2700   char **call_args;
2701   LK_ENTRY *group_base;
2702   int  group_count;
2703   char filter[1024];
2704   char *attr_array[3];
2705   
2706   call_args = ptr;
2707
2708   if(UseGroupUniversal)
2709     groupTypeControl = ADS_GROUP_TYPE_UNIVERSAL_GROUP;
2710   else 
2711     groupTypeControl = ADS_GROUP_TYPE_GLOBAL_GROUP;
2712
2713   if (!check_string(av[L_NAME]))
2714     {
2715       com_err(whoami, 0, "Unable to process invalid LDAP list name %s", 
2716               av[L_NAME]);
2717       return(AD_INVALID_NAME);
2718     }
2719
2720   updateGroup = (int)call_args[4];
2721   memset(group_ou, 0, sizeof(group_ou));
2722   memset(group_membership, 0, sizeof(group_membership));
2723   security_flag = 0;
2724
2725   get_group_membership(group_membership, group_ou, &security_flag, av);
2726
2727   strcpy(new_group_name, av[L_NAME]);
2728   sprintf(new_dn, "cn=%s,%s,%s", new_group_name, group_ou, call_args[1]);
2729   sprintf(contact_mail, "%s@mit.edu", av[L_NAME]);
2730   sprintf(mail, "%s@%s", av[L_NAME], lowercase(ldap_domain));
2731   sprintf(mail_nickname, "%s", av[L_NAME]);
2732
2733   if (security_flag)
2734     groupTypeControl |= ADS_GROUP_TYPE_SECURITY_ENABLED;
2735   
2736   sprintf(sam_group_name, "%s%s", av[L_NAME], group_suffix);
2737
2738   if (!updateGroup)
2739     {
2740       sprintf(groupTypeControlStr, "%ld", groupTypeControl);
2741       groupTypeControl_v[0] = groupTypeControlStr;
2742
2743       strcpy(cn_group_name, av[L_NAME]);
2744       
2745       samAccountName_v[0] = sam_group_name;
2746       name_v[0] = new_group_name;
2747       cn_v[0] = new_group_name;
2748
2749       n = 0;
2750       ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
2751
2752       if(ActiveDirectory)
2753         {
2754           ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2755         } 
2756       else
2757         {
2758           mitMoiraPublic_v[0] = av[L_PUBLIC];
2759           mitMoiraHidden_v[0] = av[L_HIDDEN];
2760           mitMoiraActive_v[0] = av[L_ACTIVE];
2761           mitMoiraNFSGroup_v[0] = av[L_NFSGROUP];
2762           ADD_ATTR("objectClass", objectClass_ldap_v, LDAP_MOD_ADD);
2763           ADD_ATTR("mitMoiraPublic", mitMoiraPublic_v, LDAP_MOD_ADD);
2764           ADD_ATTR("mitMoiraHidden", mitMoiraHidden_v, LDAP_MOD_ADD);
2765           ADD_ATTR("mitMoiraActive", mitMoiraActive_v, LDAP_MOD_ADD);
2766           ADD_ATTR("mitMoiraNFSGroup", mitMoiraNFSGroup_v, LDAP_MOD_ADD);
2767           
2768           if(atoi(av[L_GROUP])) 
2769             {
2770               gidNumber_v[0] = av[L_GID];
2771               ADD_ATTR("gidNumber", gidNumber_v, LDAP_MOD_ADD);
2772             }
2773         }
2774
2775       ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
2776       ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2777       ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2778
2779       if (Exchange)
2780         {
2781           if(atoi(av[L_MAILLIST])) 
2782             {
2783               group_count = 0;
2784               group_base = NULL;
2785               
2786               sprintf(filter, "(&(objectClass=user)(cn=%s))", av[L_NAME]);
2787               attr_array[0] = "cn";
2788               attr_array[1] = NULL;
2789               
2790               if ((rc = linklist_build((LDAP *)call_args[0], call_args[1], 
2791                                        filter, attr_array, &group_base, 
2792                                        &group_count,
2793                                        LDAP_SCOPE_SUBTREE)) != 0)
2794                 {
2795                   com_err(whoami, 0, "Unable to process group %s : %s",
2796                           av[L_NAME], ldap_err2string(rc));
2797                   return(rc);
2798                 }
2799               
2800               if (group_count)
2801                 {
2802                   com_err(whoami, 0, "Object already exists with name %s",
2803                           av[L_NAME]);
2804                   MailDisabled++;
2805                 }
2806         
2807               linklist_free(group_base);
2808               group_base = NULL;
2809               group_count = 0;
2810             }
2811           
2812           if(atoi(av[L_MAILLIST]) && !MailDisabled && email_isvalid(mail)) 
2813             {
2814               mail_nickname_v[0] = mail_nickname;
2815               report_to_originator_v[0] = "TRUE";
2816
2817               ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_ADD);
2818               ADD_ATTR("reportToOriginator", report_to_originator_v, 
2819                        LDAP_MOD_ADD);
2820             }
2821         }
2822       else
2823         {
2824           if(atoi(av[L_MAILLIST]) && email_isvalid(contact_mail)) 
2825             {
2826               mail_v[0] = contact_mail;
2827               ADD_ATTR("mail", mail_v, LDAP_MOD_ADD);
2828
2829               if(!ActiveDirectory)
2830                 {
2831                   null_v[0] = "/dev/null";
2832                   ADD_ATTR("mailRoutingAddress", null_v, LDAP_MOD_ADD);
2833                   ADD_ATTR("mitMoiraMail", mail_v, LDAP_MOD_ADD);
2834                 }
2835             }
2836         }
2837       
2838       if (strlen(av[L_DESC]) != 0)
2839         {
2840           desc_v[0] = av[L_DESC];
2841           ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2842         }
2843       
2844       ADD_ATTR("groupType", groupTypeControl_v, LDAP_MOD_ADD);
2845
2846       if (strlen(av[L_ACE_NAME]) != 0)
2847         {
2848           sprintf(info, "The Administrator of this list is: %s", 
2849                   av[L_ACE_NAME]);
2850           info_v[0] = info;
2851           ADD_ATTR("info", info_v, LDAP_MOD_ADD);
2852         }
2853
2854       if (strlen(call_args[5]) != 0)
2855         {
2856           mitMoiraId_v[0] = call_args[5];
2857           ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_ADD);
2858         }
2859           
2860       mods[n] = NULL;
2861       
2862       rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
2863       
2864       for (i = 0; i < n; i++)
2865         free(mods[i]);
2866
2867       if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2868         {
2869           com_err(whoami, 0, "Unable to create list %s in directory : %s",
2870                   av[L_NAME], ldap_err2string(rc));
2871           callback_rc = rc;
2872           return(rc);
2873         }
2874     }
2875
2876   if ((rc == LDAP_ALREADY_EXISTS) || (updateGroup))
2877     {
2878       rc = attribute_update((LDAP *)call_args[0], new_dn, av[L_DESC], 
2879                             "description", av[L_NAME]);
2880       sprintf(info, "The Administrator of this list is: %s", av[L_ACE_NAME]);
2881
2882       rc = attribute_update((LDAP *)call_args[0], new_dn, info, "info", 
2883                                 av[L_NAME]);
2884
2885       n = 0;
2886
2887       if (strlen(call_args[5]) != 0)
2888         {
2889           mitMoiraId_v[0] = call_args[5];
2890           ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
2891         }
2892
2893       if (!(atoi(av[L_ACTIVE])))
2894         {
2895           member_v[0] = NULL;
2896           ADD_ATTR("member", member_v, LDAP_MOD_REPLACE);
2897         }
2898    
2899       if (!ActiveDirectory) 
2900         {
2901           mitMoiraPublic_v[0] = av[L_PUBLIC];
2902           mitMoiraHidden_v[0] = av[L_HIDDEN];
2903           mitMoiraActive_v[0] = av[L_ACTIVE];
2904           mitMoiraNFSGroup_v[0] = av[L_NFSGROUP];
2905           ADD_ATTR("mitMoiraPublic", mitMoiraPublic_v, LDAP_MOD_REPLACE);
2906           ADD_ATTR("mitMoiraHidden", mitMoiraHidden_v, LDAP_MOD_REPLACE);
2907           ADD_ATTR("mitMoiraActive", mitMoiraActive_v, LDAP_MOD_REPLACE);
2908           ADD_ATTR("mitMoiraNFSGroup", mitMoiraNFSGroup_v, LDAP_MOD_REPLACE);
2909           
2910           if(atoi(av[L_GROUP])) 
2911             {
2912               gidNumber_v[0] = av[L_GID];
2913               ADD_ATTR("gidNumber", gidNumber_v, LDAP_MOD_REPLACE);
2914             }
2915           else
2916             {
2917               ADD_ATTR("gidNumber", gidNumber_v, LDAP_MOD_REPLACE);
2918             }
2919         }
2920
2921       if (Exchange)
2922         {
2923           if(atoi(av[L_MAILLIST])) 
2924             {
2925               group_count = 0;
2926               group_base = NULL;
2927               
2928               sprintf(filter, "(&(objectClass=user)(cn=%s))", av[L_NAME]);
2929               attr_array[0] = "cn";
2930               attr_array[1] = NULL;
2931               
2932               if ((rc = linklist_build((LDAP *)call_args[0], call_args[1], 
2933                                        filter, attr_array, &group_base, 
2934                                        &group_count,
2935                                        LDAP_SCOPE_SUBTREE)) != 0)
2936                 {
2937                   com_err(whoami, 0, "Unable to process group %s : %s",
2938                           av[L_NAME], ldap_err2string(rc));
2939                   return(rc);
2940                 }
2941               
2942               if (group_count)
2943                 {
2944                   com_err(whoami, 0, "Object already exists with name %s",
2945                           av[L_NAME]);
2946                   MailDisabled++;
2947                 }
2948               
2949               linklist_free(group_base);
2950               group_base = NULL;
2951               group_count = 0;
2952             }
2953
2954           if (atoi(av[L_MAILLIST]) && !MailDisabled && email_isvalid(mail)) 
2955             {
2956               mail_nickname_v[0] = mail_nickname;
2957               report_to_originator_v[0] = "TRUE";
2958
2959               ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_REPLACE);
2960               ADD_ATTR("reportToOriginator", report_to_originator_v, 
2961                        LDAP_MOD_REPLACE);
2962             }
2963           else 
2964             {
2965               mail_v[0] = NULL;
2966               mail_nickname_v[0] = NULL;
2967               proxy_address_v[0] = NULL;
2968               legacy_exchange_dn_v[0] = NULL;
2969               address_book_v[0] = NULL;
2970               report_to_originator_v[0] = NULL;
2971
2972               ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_REPLACE);
2973               ADD_ATTR("proxyAddresses", proxy_address_v, LDAP_MOD_REPLACE);
2974               ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
2975               ADD_ATTR("legacyExchangeDN", legacy_exchange_dn_v, 
2976                        LDAP_MOD_REPLACE);
2977               ADD_ATTR("showInAddressBook", address_book_v, LDAP_MOD_REPLACE);
2978               ADD_ATTR("reportToOriginator", report_to_originator_v, 
2979                        LDAP_MOD_REPLACE);
2980             }
2981         }
2982       else
2983         {
2984           if (atoi(av[L_MAILLIST]) && email_isvalid(contact_mail)) 
2985             {
2986               mail_v[0] = contact_mail;
2987               ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
2988
2989               if(!ActiveDirectory)
2990                 {
2991                   null_v[0] = "/dev/null";
2992                   ADD_ATTR("mailRoutingAddress", null_v, LDAP_MOD_REPLACE);
2993                   ADD_ATTR("mitMoiraMail", mail_v, LDAP_MOD_REPLACE);
2994                 }
2995             }
2996           else
2997             {
2998               mail_v[0] = NULL;
2999               ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
3000
3001               if(!ActiveDirectory)
3002                 {
3003                   null_v[0] = NULL;
3004                   ADD_ATTR("mailRoutingAddress", null_v, LDAP_MOD_REPLACE);
3005                   ADD_ATTR("mitMoiraMail", mail_v, LDAP_MOD_REPLACE);
3006                 }
3007             }
3008         }
3009    
3010       mods[n] = NULL;
3011       rc = LDAP_SUCCESS;
3012
3013       if (n != 0)
3014         {
3015           rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
3016
3017           for (i = 0; i < n; i++)
3018               free(mods[i]);
3019
3020           if (rc != LDAP_SUCCESS)
3021             {
3022               com_err(whoami, 0, "Unable to update list %s in directory : %s",
3023                       av[L_NAME], ldap_err2string(rc));
3024               callback_rc = rc;
3025               return(rc);
3026             }
3027         }
3028     }
3029
3030   ProcessGroupSecurity((LDAP *)call_args[0], call_args[1], av[L_NAME], 
3031                        atoi(av[L_HIDDEN]),  av[L_ACE_TYPE], av[L_ACE_NAME]);
3032
3033   return(LDAP_SUCCESS);
3034 }
3035
3036 int ProcessGroupSecurity(LDAP *ldap_handle, char *dn_path, 
3037                          char *TargetGroupName, int HiddenGroup, 
3038                          char *AceType, char *AceName)
3039 {
3040   char          filter_exp[1024];
3041   char          *attr_array[5];
3042   char          search_path[512];
3043   char          root_ou[128];
3044   char          TemplateDn[512];
3045   char          TemplateSamName[128];
3046   char          TargetDn[512];
3047   char          TargetSamName[128];
3048   char          AceSamAccountName[128];
3049   char          AceDn[256];
3050   unsigned char AceSid[128];
3051   unsigned char UserTemplateSid[128];
3052   char          acBERBuf[N_SD_BER_BYTES];
3053   char          GroupSecurityTemplate[256];
3054   char          hide_addres_lists[256];
3055   char          address_book[256];
3056   char          *hide_address_lists_v[] = {NULL, NULL};
3057   char          *address_book_v[] = {NULL, NULL};
3058   char          *owner_v[] = {NULL, NULL};
3059   int           AceSidCount;
3060   int           UserTemplateSidCount;
3061   int           group_count;
3062   int           n;
3063   int           i;
3064   int           rc;
3065   int           nVal;
3066   ULONG         dwInfo;
3067   int           array_count = 0;
3068   LDAPMod       *mods[20];
3069   LK_ENTRY      *group_base;
3070   LDAP_BERVAL   **ppsValues;
3071   LDAPControl sControl = {"1.2.840.113556.1.4.801",
3072                           { N_SD_BER_BYTES, acBERBuf },
3073                           TRUE
3074                          };
3075   LDAPControl *apsServerControls[] = {&sControl, NULL};
3076   LDAPMessage *psMsg;
3077
3078   dwInfo = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | 
3079     DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;
3080   BEREncodeSecurityBits(dwInfo, acBERBuf);
3081
3082   sprintf(search_path, "%s,%s", group_ou_root, dn_path);
3083   sprintf(filter_exp, "(sAMAccountName=%s%s)", TargetGroupName, group_suffix);
3084   attr_array[0] = "sAMAccountName";
3085   attr_array[1] = NULL;
3086   group_count = 0;
3087   group_base = NULL;
3088
3089   if ((rc = linklist_build(ldap_handle, search_path, filter_exp, attr_array, 
3090                            &group_base, &group_count, 
3091                            LDAP_SCOPE_SUBTREE) != 0))
3092     return(1);
3093
3094   if (group_count != 1)
3095     {
3096       linklist_free(group_base);
3097       return(1);
3098     }
3099
3100   strcpy(TargetDn, group_base->dn);
3101   strcpy(TargetSamName, group_base->value);
3102   linklist_free(group_base);
3103   group_base = NULL;
3104   group_count = 0;
3105
3106   UserTemplateSidCount = 0;
3107   memset(UserTemplateSid, '\0', sizeof(UserTemplateSid));
3108   memset(AceSamAccountName, '\0', sizeof(AceSamAccountName));
3109   memset(AceSid, '\0', sizeof(AceSid));
3110   AceSidCount = 0;
3111   group_base = NULL;
3112   group_count = 0;
3113
3114   if (strlen(AceName) != 0)
3115     {
3116       if (!strcmp(AceType, "LIST"))
3117         {
3118           sprintf(AceSamAccountName, "%s%s", AceName, group_suffix);
3119           strcpy(root_ou, group_ou_root);
3120         }
3121       else if (!strcmp(AceType, "USER"))
3122         {
3123           sprintf(AceSamAccountName, "%s", AceName);
3124           strcpy(root_ou, user_ou);
3125         }
3126
3127       if (ActiveDirectory)
3128         {
3129           if (strlen(AceSamAccountName) != 0)
3130             {
3131               sprintf(search_path, "%s", dn_path);
3132               sprintf(filter_exp, "(sAMAccountName=%s)", AceSamAccountName);
3133               attr_array[0] = "objectSid";
3134               attr_array[1] = NULL;
3135               group_count = 0;
3136               group_base = NULL;
3137               
3138               if ((rc = linklist_build(ldap_handle, search_path, filter_exp, 
3139                                        attr_array, &group_base, &group_count, 
3140                                        LDAP_SCOPE_SUBTREE) != 0))
3141                 return(1);
3142               if (group_count == 1)
3143                 {
3144                   strcpy(AceDn, group_base->dn);
3145                   AceSidCount = group_base->length;
3146                   memcpy(AceSid, group_base->value, AceSidCount);
3147                 }
3148               linklist_free(group_base);
3149               group_base = NULL;
3150               group_count = 0;
3151             }
3152         }
3153       else
3154         {
3155           if (strlen(AceSamAccountName) != 0)
3156             {
3157               sprintf(search_path, "%s", dn_path);
3158               sprintf(filter_exp, "(sAMAccountName=%s)", AceSamAccountName);
3159               attr_array[0] = "samAccountName";
3160               attr_array[1] = NULL;
3161               group_count = 0;
3162               group_base = NULL;
3163               
3164               if ((rc = linklist_build(ldap_handle, search_path, filter_exp, 
3165                                        attr_array, &group_base, &group_count, 
3166                                        LDAP_SCOPE_SUBTREE) != 0))
3167                 return(1);
3168               if (group_count == 1)
3169                 {
3170                   strcpy(AceDn, group_base->dn);
3171                 }
3172               linklist_free(group_base);
3173               group_base = NULL;
3174               group_count = 0;
3175             }
3176         }
3177     }
3178
3179   if (!ActiveDirectory) 
3180     {
3181       if (strlen(AceDn) != 0) 
3182         {
3183           owner_v[0] = strdup(AceDn);
3184           n = 0;
3185           ADD_ATTR("owner", owner_v, LDAP_MOD_REPLACE);
3186
3187           mods[n] = NULL;
3188
3189           rc = ldap_modify_s(ldap_handle, TargetDn, mods);
3190           
3191           for (i = 0; i < n; i++)
3192             free(mods[i]);
3193
3194           if (rc != LDAP_SUCCESS)
3195             com_err(whoami, 0, "Unable to set owner for group %s : %s",
3196               TargetGroupName, ldap_err2string(rc));
3197         }
3198
3199       return(rc);
3200     }
3201   
3202   if (AceSidCount == 0)
3203     {
3204       com_err(whoami, 0, "Group %s: Administrator: %s, Type: %s - does not "
3205               "have a directory SID.", TargetGroupName, AceName, AceType);
3206       com_err(whoami, 0, "   Non-admin security group template will be used.");
3207     }
3208   else
3209     {
3210       sprintf(search_path, "%s,%s", security_template_ou, dn_path);
3211       sprintf(filter_exp, "(sAMAccountName=%s)", "UserTemplate.u");
3212       attr_array[0] = "objectSid";
3213       attr_array[1] = NULL;
3214
3215       group_count = 0;
3216       group_base = NULL;
3217
3218       if ((rc = linklist_build(ldap_handle, search_path, filter_exp, 
3219                                attr_array, &group_base, &group_count, 
3220                                LDAP_SCOPE_SUBTREE) != 0))
3221         return(1);
3222
3223       if ((rc != 0) || (group_count != 1))
3224         {
3225           com_err(whoami, 0, "Unable to process user security template: %s", 
3226                   "UserTemplate");
3227           AceSidCount = 0;
3228         }
3229       else
3230         {
3231           UserTemplateSidCount = group_base->length;
3232           memcpy(UserTemplateSid, group_base->value, UserTemplateSidCount);
3233         }
3234       linklist_free(group_base);
3235       group_base = NULL;
3236       group_count = 0;
3237     }
3238
3239   if (HiddenGroup)
3240     {
3241       if (AceSidCount == 0)
3242         {
3243           strcpy(GroupSecurityTemplate, HIDDEN_GROUP);
3244           sprintf(filter_exp, "(sAMAccountName=%s)", HIDDEN_GROUP);
3245         }
3246       else
3247         {
3248           strcpy(GroupSecurityTemplate, HIDDEN_GROUP_WITH_ADMIN);
3249           sprintf(filter_exp, "(sAMAccountName=%s)", HIDDEN_GROUP_WITH_ADMIN);
3250         }
3251     }
3252   else
3253     {
3254       if (AceSidCount == 0)
3255         {
3256           strcpy(GroupSecurityTemplate, NOT_HIDDEN_GROUP);
3257           sprintf(filter_exp, "(sAMAccountName=%s)", NOT_HIDDEN_GROUP);
3258         }
3259       else
3260         {
3261           strcpy(GroupSecurityTemplate, NOT_HIDDEN_GROUP_WITH_ADMIN);
3262           sprintf(filter_exp, "(sAMAccountName=%s)", 
3263                   NOT_HIDDEN_GROUP_WITH_ADMIN);
3264         }
3265     }
3266
3267   sprintf(search_path, "%s,%s", security_template_ou, dn_path);
3268   attr_array[0] = "sAMAccountName";
3269   attr_array[1] = NULL;
3270   group_count = 0;
3271   group_base = NULL;
3272
3273   if ((rc = linklist_build(ldap_handle, search_path, filter_exp, attr_array, 
3274                            &group_base, &group_count, 
3275                            LDAP_SCOPE_SUBTREE) != 0))
3276     return(1);
3277
3278   if (group_count != 1)
3279     {
3280       linklist_free(group_base);
3281       com_err(whoami, 0, "Unable to process group security template: %s - "
3282               "security not set", GroupSecurityTemplate);
3283       return(1);
3284     }
3285
3286   strcpy(TemplateDn, group_base->dn);
3287   strcpy(TemplateSamName, group_base->value);
3288   linklist_free(group_base);
3289   group_base = NULL;
3290   group_count = 0;
3291   
3292   sprintf(filter_exp, "(sAMAccountName=%s)", TemplateSamName);
3293   rc = ldap_search_ext_s(ldap_handle,
3294                          TemplateDn,
3295                          LDAP_SCOPE_SUBTREE,
3296                          filter_exp,
3297                          NULL,
3298                          0,
3299                          apsServerControls,
3300                          NULL,
3301                          NULL,
3302                          0,
3303                          &psMsg);
3304
3305   if ((psMsg = ldap_first_entry(ldap_handle, psMsg)) == NULL)
3306     {
3307       com_err(whoami, 0, "Unable to find group security template: %s - "
3308               "security not set", GroupSecurityTemplate);
3309       return(1);
3310     }
3311
3312   ppsValues = ldap_get_values_len(ldap_handle, psMsg, "ntSecurityDescriptor");
3313
3314   if (ppsValues == NULL)
3315     {
3316       com_err(whoami, 0, "Unable to find group security descriptor for group "
3317               "%s - security not set", GroupSecurityTemplate);
3318       return(1);
3319     }
3320   
3321   if (AceSidCount != 0)
3322     {
3323       for (nVal = 0; ppsValues[nVal] != NULL; nVal++)
3324         {
3325           for (i = 0; 
3326                i < (int)(ppsValues[nVal]->bv_len - UserTemplateSidCount); i++)
3327             {
3328               if (!memcmp(&ppsValues[nVal]->bv_val[i], UserTemplateSid, 
3329                           UserTemplateSidCount))
3330                 {
3331                   memcpy(&ppsValues[nVal]->bv_val[i], AceSid, AceSidCount);
3332                   break;
3333                 }
3334             }
3335         }
3336     }
3337
3338   n = 0;
3339   ADD_ATTR("ntSecurityDescriptor", (char **)ppsValues, 
3340            LDAP_MOD_REPLACE | LDAP_MOD_BVALUES);
3341
3342   if (Exchange)
3343     {
3344       if(HiddenGroup) 
3345         {
3346           hide_address_lists_v[0] = "TRUE";
3347           address_book_v[0] = NULL;
3348           ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v, 
3349                    LDAP_MOD_REPLACE);
3350           ADD_ATTR("showInAddressBook", address_book_v, LDAP_MOD_REPLACE);
3351         } else {
3352           hide_address_lists_v[0] = NULL;
3353           ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v, 
3354                    LDAP_MOD_REPLACE);
3355         }
3356     }
3357
3358   mods[n] = NULL;
3359
3360   rc = ldap_modify_s(ldap_handle, TargetDn, mods);
3361
3362   for (i = 0; i < n; i++)
3363     free(mods[i]);
3364
3365   ldap_value_free_len(ppsValues);
3366   ldap_msgfree(psMsg);
3367
3368   if (rc != LDAP_SUCCESS)
3369     {
3370       com_err(whoami, 0, "Unable to set security settings for group %s : %s",
3371               TargetGroupName, ldap_err2string(rc));
3372
3373       if (AceSidCount != 0)
3374         {
3375           com_err(whoami, 0, 
3376                   "Trying to set security for group %s without admin.",
3377                   TargetGroupName);
3378
3379           if (rc = ProcessGroupSecurity(ldap_handle, dn_path, TargetGroupName, 
3380                                         HiddenGroup, "", ""))
3381             {
3382               com_err(whoami, 0, "Unable to set security for group %s.",
3383                       TargetGroupName);
3384               return(rc);
3385             }
3386         }
3387       return(rc);
3388     }
3389
3390   return(rc);
3391 }
3392
3393 int group_delete(LDAP *ldap_handle, char *dn_path, char *group_name, 
3394                  char *group_membership, char *MoiraId)
3395 {
3396   LK_ENTRY  *group_base;
3397   char      temp[512];
3398   char      filter[128];
3399   int       group_count;
3400   int       rc;
3401
3402   if (!check_string(group_name))
3403     {
3404       com_err(whoami, 0, 
3405               "Unable to process invalid LDAP list name %s", group_name);
3406       return(AD_INVALID_NAME);
3407     }
3408
3409   memset(filter, '\0', sizeof(filter));
3410   group_count = 0;
3411   group_base = NULL;
3412   sprintf(temp, "%s,%s", group_ou_root, dn_path);
3413
3414   if (rc = ad_get_group(ldap_handle, temp, group_name, 
3415                         group_membership, MoiraId, 
3416                         "samAccountName", &group_base, 
3417                         &group_count, filter))
3418     return(rc);
3419
3420   if (group_count == 1)
3421     {
3422       if ((rc = ldap_delete_s(ldap_handle, group_base->dn)) != LDAP_SUCCESS)
3423         {
3424           linklist_free(group_base);
3425           com_err(whoami, 0, "Unable to delete list %s from directory : %s",
3426                   group_name, ldap_err2string(rc));
3427           return(rc);
3428         }
3429       linklist_free(group_base);
3430     }
3431   else
3432     {
3433       linklist_free(group_base);
3434       com_err(whoami, 0, "Unable to find list %s in directory.", group_name);
3435       return(AD_NO_GROUPS_FOUND);
3436     }
3437   
3438   return(0);
3439 }
3440
3441 int BEREncodeSecurityBits(ULONG uBits, char *pBuffer)
3442 {
3443     *pBuffer++ = 0x30;
3444     *pBuffer++ = 0x03;
3445     *pBuffer++ = 0x02;
3446     *pBuffer++ = 0x00;
3447     return(N_SD_BER_BYTES);
3448 }
3449
3450 int process_lists(int ac, char **av, void *ptr)
3451 {
3452   int   rc;
3453   int   security_flag;
3454   char  group_ou[256];
3455   char  group_membership[2];
3456   char  **call_args;
3457
3458   call_args = ptr;
3459
3460   security_flag = 0;
3461   memset(group_ou, '\0', sizeof(group_ou));
3462   memset(group_membership, '\0', sizeof(group_membership));
3463   get_group_membership(group_membership, group_ou, &security_flag, av);
3464   rc = populate_group((LDAP *)call_args[0], (char *)call_args[1], 
3465                       av[L_NAME], group_ou, group_membership, 
3466                       security_flag, "", 1);
3467
3468   return(0);
3469 }
3470
3471 int member_list_build(int ac, char **av, void *ptr)
3472 {
3473   LK_ENTRY  *linklist;
3474   char      temp[1024];
3475   char      **call_args;
3476   char      *s;
3477   call_args = ptr;
3478
3479   strcpy(temp, av[ACE_NAME]);
3480   StringTrim(temp);
3481   
3482   if (!check_string(temp))
3483     return(0);
3484
3485   if (!strcmp(av[ACE_TYPE], "USER"))
3486     {
3487       if (!((int)call_args[3] & MOIRA_USERS))
3488         return(0);
3489     }
3490   else if (!strcmp(av[ACE_TYPE], "STRING"))
3491     {
3492       if (Exchange)
3493         {
3494           if((s = strchr(temp, '@')) == (char *) NULL) 
3495             {
3496               strcat(temp, "@mit.edu");
3497             }
3498           
3499           if(!strncasecmp(&temp[strlen(temp) - 6], ".LOCAL", 6))
3500             {
3501               s = strrchr(temp, '.');
3502               *s = '\0';
3503               strcat(s, ".mit.edu");
3504             }
3505         }
3506
3507       if (!((int)call_args[3] & MOIRA_STRINGS))
3508         return(0);
3509         
3510       if (contact_create((LDAP *)call_args[0], call_args[1], temp, contact_ou))
3511         return(0);
3512     }
3513   else if (!strcmp(av[ACE_TYPE], "LIST"))
3514     {
3515       if (!((int)call_args[3] & MOIRA_LISTS))
3516         return(0);
3517     }
3518   else if (!strcmp(av[ACE_TYPE], "KERBEROS"))
3519     {
3520       if (!((int)call_args[3] & MOIRA_KERBEROS))
3521         return(0);
3522
3523       if (contact_create((LDAP *)call_args[0], call_args[1], temp, 
3524                          kerberos_ou))
3525         return(0);
3526
3527     }
3528   else if (!strcmp(av[ACE_TYPE], "MACHINE"))
3529     {
3530       if (!((int)call_args[3] & MOIRA_MACHINE))
3531         return(0);
3532     }
3533   else
3534     return(0);
3535
3536   linklist = member_base;
3537
3538   while (linklist)
3539     {
3540     if (!strcasecmp(temp, linklist->member) &&
3541         !strcasecmp(av[ACE_TYPE], linklist->type))
3542       return(0);
3543
3544     linklist = linklist->next;
3545     }
3546
3547   linklist = calloc(1, sizeof(LK_ENTRY));
3548   linklist->op = 1;
3549   linklist->dn = NULL;
3550   linklist->list = calloc(1, strlen(call_args[2]) + 1);
3551   strcpy(linklist->list, call_args[2]);
3552   linklist->type = calloc(1, strlen(av[ACE_TYPE]) + 1);
3553   strcpy(linklist->type, av[ACE_TYPE]);
3554   linklist->member = calloc(1, strlen(temp) + 1);
3555   strcpy(linklist->member, temp);
3556   linklist->next = member_base;
3557   member_base = linklist;
3558
3559   return(0);
3560 }
3561
3562 int member_remove(LDAP *ldap_handle, char *dn_path, char *group_name, 
3563                   char *group_ou, char *group_membership, char *user_name,
3564                   char *UserOu, char *MoiraId)
3565 {
3566   char        distinguished_name[1024];
3567   char        *modvalues[2];
3568   char        temp[256];
3569   char        filter[128];
3570   char        *attr_array[3];
3571   int         group_count;
3572   int         i;
3573   int         n;
3574   LDAPMod     *mods[20];
3575   LK_ENTRY    *group_base;
3576   ULONG       rc;
3577   char        *s;
3578
3579   if (max_group_members && (group_members < max_group_members))
3580     return(0);
3581
3582   if (!check_string(group_name))
3583     return(AD_INVALID_NAME);
3584
3585   if(!contains_member(ldap_handle, dn_path, group_name, UserOu,
3586                       escape_string(user_name)))
3587     return(0);
3588
3589   memset(filter, '\0', sizeof(filter));
3590   group_base = NULL;
3591   group_count = 0;
3592
3593   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
3594                         group_membership, MoiraId, 
3595                         "samAccountName", &group_base, 
3596                         &group_count, filter))
3597     return(rc);
3598
3599   if (group_count != 1)
3600     {
3601       com_err(whoami, 0, "Unable to find list %s in directory",
3602               group_name);
3603       linklist_free(group_base);
3604       group_base = NULL;
3605       group_count = 0;
3606       goto cleanup;
3607     }
3608
3609   strcpy(distinguished_name, group_base->dn);
3610   linklist_free(group_base);
3611   group_base = NULL;
3612   group_count = 0;
3613
3614   if(ActiveDirectory)
3615     {
3616       sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
3617     }
3618   else
3619     {
3620       if(!strcmp(UserOu, user_ou))
3621         sprintf(temp, "uid=%s,%s,%s", user_name, UserOu, dn_path);
3622       else
3623         sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
3624     }
3625
3626   modvalues[0] = temp;
3627   modvalues[1] = NULL;
3628
3629   n = 0;
3630   ADD_ATTR("member", modvalues, LDAP_MOD_DELETE);
3631   mods[n] = NULL;
3632   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
3633
3634   for (i = 0; i < n; i++)
3635     free(mods[i]);
3636
3637   if (rc == LDAP_UNWILLING_TO_PERFORM)
3638     rc = LDAP_SUCCESS;
3639
3640   if (rc != LDAP_SUCCESS)
3641     {
3642       com_err(whoami, 0, "Unable to modify list %s members : %s",
3643               group_name, ldap_err2string(rc));
3644       goto cleanup;
3645     }
3646
3647   if ((!strcmp(UserOu, contact_ou)) || (!strcmp(UserOu, kerberos_ou))) 
3648     {
3649       if (Exchange)
3650         {
3651           if(!strcmp(UserOu, contact_ou) && 
3652              ((s = strstr(user_name, "@mit.edu")) != (char *) NULL))
3653             {
3654               memset(temp, '\0', sizeof(temp));
3655               strcpy(temp, user_name);
3656               s = strchr(temp, '@');
3657               *s = '\0';
3658               
3659               sprintf(filter, "(&(objectClass=user)(mailNickName=%s))", temp);
3660           
3661               if ((rc = linklist_build(ldap_handle, dn_path, filter, NULL,
3662                                        &group_base, &group_count, 
3663                                        LDAP_SCOPE_SUBTREE) != 0))
3664                 return(rc);       
3665               
3666               if(group_count)
3667                 goto cleanup;
3668               
3669               linklist_free(group_base);
3670               group_base = NULL;
3671               group_count = 0;
3672             }
3673           
3674           sprintf(filter, "(distinguishedName=%s)", temp);
3675           attr_array[0] = "memberOf";
3676           attr_array[1] = NULL;
3677           
3678           if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
3679                                    &group_base, &group_count, 
3680                                    LDAP_SCOPE_SUBTREE) != 0))
3681             return(rc);
3682           
3683
3684           if(!group_count) 
3685             {
3686               com_err(whoami, 0, "Removing unreferenced object %s", temp);
3687           
3688               if ((rc = ldap_delete_s(ldap_handle, temp)) != 0) 
3689                 return(rc);
3690             }
3691         }
3692     }
3693
3694  cleanup:
3695   return(rc);
3696 }
3697
3698 int member_add(LDAP *ldap_handle, char *dn_path, char *group_name, 
3699                char *group_ou, char *group_membership, char *user_name, 
3700                char *UserOu, char *MoiraId)
3701 {
3702   char        distinguished_name[1024];
3703   char        *modvalues[2];
3704   char        temp[256];
3705   char        filter[128];
3706   int         group_count;
3707   int         n;
3708   int         i;
3709   LDAPMod     *mods[20];
3710   LK_ENTRY    *group_base;
3711   ULONG       rc;
3712
3713   if (max_group_members && (group_members < max_group_members))
3714     return(0);
3715
3716   if (!check_string(group_name))
3717     return(AD_INVALID_NAME);
3718
3719   if(contains_member(ldap_handle, dn_path, group_name, UserOu, user_name) > 0)
3720     return(0);
3721
3722   rc = 0;
3723   memset(filter, '\0', sizeof(filter));
3724   group_base = NULL;
3725   group_count = 0;
3726
3727   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
3728                         group_membership, MoiraId, 
3729                         "samAccountName", &group_base, 
3730                         &group_count, filter))
3731     return(rc);
3732
3733   if (group_count != 1)
3734     {
3735       linklist_free(group_base);
3736       group_base = NULL;
3737       group_count = 0;
3738       com_err(whoami, 0, "Unable to find list %s %d in directory",
3739               group_name, group_count);
3740       return(AD_MULTIPLE_GROUPS_FOUND);
3741     }
3742
3743   strcpy(distinguished_name, group_base->dn);
3744   linklist_free(group_base);
3745   group_base = NULL;
3746   group_count = 0;
3747
3748   if(ActiveDirectory)
3749     {
3750       sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
3751     }
3752   else 
3753     {
3754       if(!strcmp(UserOu, user_ou))
3755         sprintf(temp, "uid=%s,%s,%s", user_name, UserOu, dn_path);
3756       else
3757         sprintf(temp, "cn=%s,%s,%s", user_name, UserOu, dn_path);
3758     }
3759
3760   modvalues[0] = temp;
3761   modvalues[1] = NULL;
3762
3763   n = 0;
3764   ADD_ATTR("member", modvalues, LDAP_MOD_ADD);
3765   mods[n] = NULL;
3766   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
3767
3768   if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
3769     rc = LDAP_SUCCESS;
3770
3771   if ((!strcmp(UserOu, contact_ou)) || (!strcmp(UserOu, kerberos_ou)))
3772     {
3773       if (rc == LDAP_UNWILLING_TO_PERFORM)
3774         rc = LDAP_SUCCESS;
3775     }
3776
3777   for (i = 0; i < n; i++)
3778     free(mods[i]);
3779
3780   if (rc != LDAP_SUCCESS)
3781     {
3782       com_err(whoami, 0, "Unable to add %s to list %s as a member : %s",
3783               user_name, group_name, ldap_err2string(rc));
3784     }
3785
3786   return(rc);
3787 }
3788
3789 int contact_remove_email(LDAP *ld, char *bind_path,
3790                          LK_ENTRY **linklist_base, int linklist_current)
3791 {
3792   LK_ENTRY  *gPtr;
3793   int       rc;
3794   char      *mail_v[] = {NULL, NULL};
3795   LDAPMod   *mods[20];
3796   int n;
3797   int i;
3798
3799   mail_v[0] = NULL;
3800
3801   n = 0;
3802   ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
3803   ADD_ATTR("mailNickName", mail_v, LDAP_MOD_REPLACE);
3804   ADD_ATTR("proxyAddresses", mail_v, LDAP_MOD_REPLACE);
3805   ADD_ATTR("targetAddress", mail_v, LDAP_MOD_REPLACE);
3806   mods[n] = NULL;
3807
3808   gPtr = (*linklist_base);
3809   
3810   while(gPtr) {
3811     rc = ldap_modify_s(ld, gPtr->dn, mods);
3812     
3813     if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
3814       {
3815         com_err(whoami, 0, "Unable to modify contact %s in directory : %s",
3816                 gPtr->dn, ldap_err2string(rc));
3817         return(rc);
3818       }
3819
3820     gPtr = gPtr->next;
3821   }
3822
3823   for (i = 0; i < n; i++)
3824     free(mods[i]);
3825   
3826     return(rc);
3827 }
3828
3829 int contact_create(LDAP *ld, char *bind_path, char *user, char *group_ou)
3830 {
3831   LDAPMod *mods[20];
3832   LK_ENTRY  *group_base;
3833   int  group_count;
3834   char new_dn[256];
3835   char cn_user_name[256];
3836   char contact_name[256];
3837   char mail_nickname[256];
3838   char proxy_address_internal[256];
3839   char proxy_address_external[256];
3840   char target_address[256];
3841   char internal_contact_name[256];
3842   char filter[128];
3843   char mail[256];
3844   char principal[256];
3845   char mit_address_book[256];
3846   char default_address_book[256];
3847   char contact_address_book[256];
3848   char uid[256];
3849   char *email_v[] = {NULL, NULL};
3850   char *cn_v[] = {NULL, NULL};
3851   char *contact_v[] = {NULL, NULL};
3852   char *uid_v[] = {NULL, NULL};
3853   char *mail_nickname_v[] = {NULL, NULL};
3854   char *proxy_address_internal_v[] = {NULL, NULL};
3855   char *proxy_address_external_v[] = {NULL, NULL};
3856   char *target_address_v[] = {NULL, NULL};
3857   char *mit_address_book_v[] = {NULL, NULL};
3858   char *default_address_book_v[] = {NULL, NULL};
3859   char *contact_address_book_v[] = {NULL, NULL};
3860   char *hide_address_lists_v[] = {NULL, NULL};
3861   char *attr_array[3];
3862   char *objectClass_v[] = {"top", "person", 
3863                            "organizationalPerson", 
3864                            "contact", NULL};
3865   char *objectClass_ldap_v[] = {"top", "person", "microsoftComTop", 
3866                                 "inetOrgPerson", "organizationalPerson",
3867                                 "contact", "mailRecipient", "eduPerson",
3868                                 NULL};
3869   char *name_v[] = {NULL, NULL};
3870   char *desc_v[] = {NULL, NULL};
3871   char *s;
3872   int  n;
3873   int  rc;
3874   int  i;
3875   char temp[256];
3876   char *c;
3877   char *mail_routing_v[] = {NULL, NULL};
3878   char *principal_v[] = {NULL, NULL};
3879
3880   if (!check_string(user))
3881     {
3882       com_err(whoami, 0, "Unable to process invalid LDAP name %s", user);
3883       return(AD_INVALID_NAME);
3884     }
3885
3886   strcpy(mail, user);
3887   strcpy(contact_name, mail);
3888   strcpy(internal_contact_name, mail);
3889   
3890   if((s = strchr(internal_contact_name, '@')) != NULL) {
3891     *s = '?';
3892   }
3893
3894   sprintf(cn_user_name,"CN=%s,%s,%s", escape_string(contact_name), group_ou, 
3895           bind_path);
3896
3897   sprintf(target_address, "SMTP:%s", contact_name);
3898   sprintf(proxy_address_external, "SMTP:%s", contact_name);
3899   sprintf(mail_nickname, "%s", internal_contact_name);
3900  
3901   cn_v[0] = cn_user_name;
3902   contact_v[0] = contact_name;
3903   uid_v[0] = uid;
3904   name_v[0] = user;
3905   desc_v[0] = "Auto account created by Moira";
3906   email_v[0] = mail;
3907   proxy_address_internal_v[0] = proxy_address_internal;
3908   proxy_address_external_v[0] = proxy_address_external;
3909   mail_nickname_v[0] = mail_nickname;
3910   target_address_v[0] = target_address;
3911   mit_address_book_v[0] = mit_address_book;
3912   default_address_book_v[0] = default_address_book;
3913   contact_address_book_v[0] = contact_address_book;
3914   strcpy(new_dn, cn_user_name);
3915   n = 0;
3916
3917   ADD_ATTR("cn", contact_v, LDAP_MOD_ADD);
3918
3919   if(!ActiveDirectory)
3920     {
3921       if(!strcmp(group_ou, contact_ou))
3922         sprintf(uid, "%s%s", contact_name, "_strings");
3923       
3924       if(!strcmp(group_ou, kerberos_ou))
3925         sprintf(uid, "%s%s", contact_name, "_kerberos");
3926
3927       uid_v[0] = uid;
3928
3929       ADD_ATTR("sn", contact_v, LDAP_MOD_ADD);
3930       ADD_ATTR("uid", uid_v, LDAP_MOD_ADD);
3931     }
3932
3933   if(ActiveDirectory)
3934     {
3935       ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
3936     }
3937   else
3938     {
3939       ADD_ATTR("objectClass", objectClass_ldap_v, LDAP_MOD_ADD);
3940     }
3941
3942   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
3943   ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
3944   ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
3945
3946   if (Exchange)
3947     {
3948       if (!strcmp(group_ou, contact_ou) && email_isvalid(mail))
3949         {
3950           group_count = 0;
3951           group_base = NULL;
3952           
3953           sprintf(filter, "(&(objectClass=user)(cn=%s))", mail);
3954           attr_array[0] = "cn";
3955           attr_array[1] = NULL;
3956
3957           if ((rc = linklist_build(ld, bind_path, filter, attr_array,
3958                                    &group_base, &group_count, 
3959                                    LDAP_SCOPE_SUBTREE)) != 0) 
3960             {
3961               com_err(whoami, 0, "Unable to process contact %s : %s", 
3962                       user, ldap_err2string(rc));
3963               return(rc);
3964             }
3965       
3966           if (group_count) 
3967             {
3968               com_err(whoami, 0, "Object already exists with name %s",
3969                       user);
3970               return(1);
3971             }
3972
3973           linklist_free(group_base);
3974           group_base = NULL;
3975           group_count = 0;
3976       
3977           sprintf(filter, "(&(objectClass=group)(cn=%s))", mail);
3978           attr_array[0] = "cn";
3979           attr_array[1] = NULL;
3980
3981           if ((rc = linklist_build(ld, bind_path, filter, attr_array,
3982                                    &group_base, &group_count, 
3983                                    LDAP_SCOPE_SUBTREE)) != 0) 
3984             {
3985               com_err(whoami, 0, "Unable to process contact %s : %s", 
3986                       user, ldap_err2string(rc));
3987               return(rc);
3988             }
3989           
3990           if (group_count) 
3991             {
3992               com_err(whoami, 0, "Object already exists with name %s",
3993                       user);
3994               return(1);
3995             }
3996   
3997           linklist_free(group_base);
3998           group_count = 0;
3999           group_base = NULL;
4000
4001           sprintf(filter, "(&(objectClass=user)(mail=%s))", mail);
4002           attr_array[0] = "cn";
4003           attr_array[1] = NULL;
4004
4005           if ((rc = linklist_build(ld, bind_path, filter, attr_array,
4006                                    &group_base, &group_count, 
4007                                    LDAP_SCOPE_SUBTREE)) != 0) 
4008             {
4009               com_err(whoami, 0, "Unable to process contact %s : %s", 
4010                       user, ldap_err2string(rc));
4011               return(rc);
4012             }
4013           
4014           if (group_count) 
4015             {
4016               com_err(whoami, 0, "Object already exists with name %s",
4017                       user);
4018               return(1);
4019             }
4020
4021           linklist_free(group_base);
4022           group_base = NULL;
4023           group_count = 0;
4024
4025           sprintf(filter, "(&(objectClass=group)(mail=%s))", mail);
4026           attr_array[0] = "cn";
4027           attr_array[1] = NULL;
4028
4029           if ((rc = linklist_build(ld, bind_path, filter, attr_array,
4030                                    &group_base, &group_count, 
4031                                    LDAP_SCOPE_SUBTREE)) != 0) 
4032             {
4033               com_err(whoami, 0, "Unable to process contact %s : %s", 
4034                       user, ldap_err2string(rc));
4035               return(rc);
4036             }
4037       
4038           if (group_count) 
4039             {
4040               com_err(whoami, 0, "Object already exists with name %s",
4041                       user);
4042               return(1);
4043             }
4044           
4045           linklist_free(group_base);
4046           group_base = NULL;
4047           group_count = 0;
4048
4049           ADD_ATTR("mail", email_v, LDAP_MOD_ADD);
4050           ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_ADD);
4051           ADD_ATTR("proxyAddresses", proxy_address_external_v, LDAP_MOD_ADD);
4052           ADD_ATTR("targetAddress", target_address_v, LDAP_MOD_ADD);
4053           
4054           hide_address_lists_v[0] = "TRUE";
4055           ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
4056                    LDAP_MOD_ADD);
4057         }
4058     }
4059
4060   if(!ActiveDirectory) 
4061     {
4062       if((c = strchr(mail, '@')) == NULL)
4063           sprintf(temp, "%s@mit.edu", mail);
4064       else
4065           sprintf(temp, "%s", mail);
4066
4067       mail_routing_v[0] = temp;
4068       email_v[0] = temp;
4069       principal_v[0] = principal;
4070
4071       if(!strcmp(group_ou, contact_ou))
4072         {
4073           ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
4074           ADD_ATTR("eduPersonPrincipalName", mail_routing_v, LDAP_MOD_ADD);
4075         }
4076     }
4077
4078   mods[n] = NULL;
4079
4080   rc = ldap_add_ext_s(ld, new_dn, mods, NULL, NULL);
4081
4082   for (i = 0; i < n; i++)
4083     free(mods[i]);
4084   
4085   if (Exchange)
4086     {
4087       if ((rc != LDAP_SUCCESS) && (rc == LDAP_ALREADY_EXISTS) &&
4088           !strcmp(group_ou, contact_ou) && email_isvalid(mail))
4089         {
4090           n = 0;
4091           
4092           ADD_ATTR("mail", email_v, LDAP_MOD_REPLACE);
4093           ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_REPLACE);
4094           ADD_ATTR("proxyAddresses", proxy_address_external_v, 
4095                    LDAP_MOD_REPLACE);
4096           ADD_ATTR("targetAddress", target_address_v, LDAP_MOD_REPLACE);
4097
4098           hide_address_lists_v[0] = "TRUE";
4099           ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
4100                    LDAP_MOD_REPLACE);
4101     
4102           mods[n] = NULL;
4103           rc = ldap_modify_s(ld, new_dn, mods);
4104       
4105           if (rc) 
4106             {
4107               com_err(whoami, 0, "Unable to update contact %s", mail);
4108             }
4109       
4110           for (i = 0; i < n; i++)
4111             free(mods[i]);
4112         }
4113     }
4114
4115   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
4116     {
4117       com_err(whoami, 0, "Unable to create contact %s : %s",
4118               user, ldap_err2string(rc));
4119       return(rc);
4120     }
4121
4122   return(0);
4123 }
4124
4125 int user_update(LDAP *ldap_handle, char *dn_path, char *user_name,
4126                 char *Uid, char *MitId, char *MoiraId, int State,
4127                 char *WinHomeDir, char *WinProfileDir, char *first,
4128                 char *middle, char *last, char *shell, char *class)
4129 {
4130   LDAPMod   *mods[20];
4131   LK_ENTRY  *group_base;
4132   int  group_count;
4133   char distinguished_name[512];
4134   char displayName[256];
4135   char address_book[1024];
4136   char *mitMoiraId_v[] = {NULL, NULL};
4137   char *mitMoiraClass_v[] = {NULL, NULL};
4138   char *mitMoiraStatus_v[] = {NULL, NULL};
4139   char *uid_v[] = {NULL, NULL};
4140   char *mitid_v[] = {NULL, NULL};
4141   char *homedir_v[] = {NULL, NULL};
4142   char *winProfile_v[] = {NULL, NULL};
4143   char *drives_v[] = {NULL, NULL};
4144   char *userAccountControl_v[] = {NULL, NULL};
4145   char *alt_recipient_v[] = {NULL, NULL};
4146   char *hide_address_lists_v[] = {NULL, NULL};
4147   char *mail_v[] = {NULL, NULL};
4148   char *gid_v[] = {NULL, NULL};
4149   char *loginshell_v[] = {NULL, NULL};
4150   char *principal_v[] = {NULL, NULL};
4151   char *address_book_v[] = {NULL, NULL, NULL, NULL, NULL};
4152   char userAccountControlStr[80];
4153   int  n;
4154   int  rc;
4155   int  i;
4156   int  OldUseSFU30;
4157   u_int userAccountControl = UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD | 
4158     UF_PASSWD_CANT_CHANGE;
4159   char filter[128];
4160   char *attr_array[3];
4161   char temp[1024];
4162   char mail[256];
4163   char filesys_name[256];
4164   char contact_mail[256];
4165   char filter_exp[1024];
4166   char search_path[512];
4167   char TemplateDn[512];
4168   char TemplateSamName[128];
4169   char alt_recipient[256];
4170   char principal[256];
4171   char status[256];
4172   char acBERBuf[N_SD_BER_BYTES];
4173   LDAPControl sControl = {"1.2.840.113556.1.4.801",
4174                           { N_SD_BER_BYTES, acBERBuf },
4175                           TRUE};
4176   LDAPControl *apsServerControls[] = {&sControl, NULL};
4177   LDAPMessage *psMsg;
4178   LDAP_BERVAL   **ppsValues;
4179   ULONG dwInfo;
4180   char *argv[3];
4181   char *homeMDB;
4182   char *homeServerName;
4183   char *save_argv[7];
4184   char search_string[256];
4185   char *p, *q;
4186   char *mail_routing_v[] = {NULL, NULL};
4187   char *mail_alternate_v[] = {NULL, NULL};
4188   char *mit_moira_imap_address_v[] = {NULL, NULL};
4189   char *deliver_and_redirect_v[] = {NULL, NULL};
4190   char *c;
4191
4192   dwInfo = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
4193     DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;
4194   BEREncodeSecurityBits(dwInfo, acBERBuf);
4195
4196   if (!check_string(user_name))
4197     {
4198       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", 
4199               user_name);
4200       return(AD_INVALID_NAME);
4201     }
4202   
4203   memset(contact_mail, '\0', sizeof(contact_mail));
4204   if(Exchange) 
4205     sprintf(contact_mail, "%s@exchange-forwarding.mit.edu", user_name);
4206   else
4207     sprintf(contact_mail, "%s@mit.edu", user_name);    
4208   memset(mail, '\0', sizeof(mail));
4209   sprintf(mail, "%s@%s", user_name, lowercase(ldap_domain));
4210   memset(alt_recipient, '\0', sizeof(alt_recipient));
4211   sprintf(alt_recipient, "cn=%s@exchange-forwarding.mit.edu,%s,%s", user_name,
4212           contact_ou, dn_path);
4213   sprintf(search_string, "@%s", uppercase(ldap_domain));
4214   memset(filesys_name, '\0', sizeof(filesys_name));
4215   sprintf(filesys_name, "%s.po", user_name);
4216
4217   if (Exchange)
4218     {
4219       if(contact_create(ldap_handle, dn_path, contact_mail, contact_ou))
4220         {
4221           com_err(whoami, 0, "Unable to create user contact %s", contact_mail);
4222         }
4223     }
4224
4225   group_count = 0;
4226   group_base = NULL;
4227
4228   memset(displayName, '\0', sizeof(displayName));
4229
4230   if (strlen(MoiraId) != 0)
4231     {
4232       if(ActiveDirectory)
4233         {
4234           sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
4235         }
4236       else
4237         {
4238           sprintf(filter, 
4239                   "(&(objectClass=mitPerson)(mitMoiraId=%s))", MoiraId);
4240         }
4241
4242       attr_array[0] = "cn";
4243       attr_array[1] = NULL;
4244       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4245                                &group_base, &group_count, 
4246                                LDAP_SCOPE_SUBTREE)) != 0)
4247         {
4248           com_err(whoami, 0, "Unable to process user %s : %s",
4249                   user_name, ldap_err2string(rc));
4250           return(rc);
4251         }
4252     }
4253
4254   if (group_count != 1)
4255     {
4256       linklist_free(group_base);
4257       group_base = NULL;
4258       group_count = 0;
4259       sprintf(filter, "(sAMAccountName=%s)", user_name);
4260       attr_array[0] = "cn";
4261       attr_array[1] = NULL;
4262       sprintf(temp, "%s,%s", user_ou, dn_path);
4263       if ((rc = linklist_build(ldap_handle, temp, filter, attr_array, 
4264                                &group_base, &group_count, 
4265                                LDAP_SCOPE_SUBTREE)) != 0)
4266         {
4267           com_err(whoami, 0, "Unable to process user %s : %s",
4268                   user_name, ldap_err2string(rc));
4269           return(rc);
4270         }
4271     }
4272
4273   if (group_count != 1)
4274     {
4275       com_err(whoami, 0, "Unable to find user %s in directory",
4276               user_name);
4277       linklist_free(group_base);
4278       return(AD_NO_USER_FOUND);
4279     }
4280
4281   strcpy(distinguished_name, group_base->dn);
4282
4283   linklist_free(group_base);
4284   group_count = 0;
4285
4286   if(!ActiveDirectory) 
4287     {
4288       if (rc = moira_connect())
4289         {
4290           critical_alert("Ldap incremental", 
4291                          "Error contacting Moira server : %s",
4292                          error_message(rc));
4293           return;
4294         }
4295   
4296       argv[0] = filesys_name;
4297
4298       if (!(rc = mr_query("get_filesys_by_label", 1, argv, save_query_info, 
4299                           save_argv)))
4300         {
4301           n = 0;
4302           ADD_ATTR("mitMoiraIMAPAddress", mit_moira_imap_address_v, 
4303                    LDAP_MOD_REPLACE);
4304           mods[n] = NULL;
4305           rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4306           
4307           if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
4308             rc = LDAP_SUCCESS;
4309
4310           if(rc)
4311             com_err(whoami, 0, 
4312                     "Unable to set the mitMoiraIMAPAddress for %s : %s",
4313                     user_name, ldap_err2string(rc));
4314
4315           sprintf(temp, "%s@%s", user_name, save_argv[FS_MACHINE]);
4316           
4317           mit_moira_imap_address_v[0]  = temp;
4318                 
4319           n = 0;
4320           ADD_ATTR("mitMoiraIMAPAddress", mit_moira_imap_address_v, 
4321                    LDAP_MOD_ADD);
4322           mods[n] = NULL;
4323           rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4324           
4325           if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
4326             rc = LDAP_SUCCESS;
4327           
4328           if(rc)
4329             com_err(whoami, 0, "Unable to set the mitMoiraIMAPAddress for " 
4330                     "%s : %s", user_name, ldap_err2string(rc));   
4331         } else if(rc==MR_NO_MATCH) {
4332           
4333           n = 0;
4334           ADD_ATTR("mitMoiraIMAPServer", mit_moira_imap_address_v, 
4335                    LDAP_MOD_REPLACE);
4336           mods[n] = NULL;
4337           rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4338           
4339           if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
4340             rc = LDAP_SUCCESS;
4341
4342           if(rc)
4343             com_err(whoami, 0, 
4344                     "Unable to set the mitMoiraIMAPAddress for %s : %s",
4345                     user_name, ldap_err2string(rc));
4346
4347         }
4348     
4349       argv[0] = user_name;
4350           
4351       if (!(rc = mr_query("get_pobox", 1, argv, save_query_info, save_argv)))
4352         {
4353           n = 0;
4354           ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_REPLACE);
4355           mods[n] = NULL;
4356           rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4357           
4358           if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
4359             rc = LDAP_SUCCESS;
4360
4361           if(rc)
4362             com_err(whoami, 0, 
4363                     "Unable to set the mailRoutingAddress for %s : %s",
4364                     user_name, ldap_err2string(rc));
4365           
4366           p = strdup(save_argv[3]);
4367           
4368           if((c = strchr(p, ',')) != NULL) 
4369             {
4370               q = strtok(p, ",");
4371               StringTrim(q);
4372
4373               if ((c = strchr(q, '@')) == NULL)
4374                 sprintf(temp, "%s@mit.edu", q);
4375               else
4376                 sprintf(temp, "%s", q);
4377               
4378               if(email_isvalid(temp) && State != US_DELETED) 
4379                 {
4380                   mail_routing_v[0]  = temp;
4381                   
4382                   n = 0;
4383                   ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
4384                   mods[n] = NULL;
4385                   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4386
4387                   if (rc == LDAP_ALREADY_EXISTS || 
4388                       rc == LDAP_TYPE_OR_VALUE_EXISTS)
4389                     rc = LDAP_SUCCESS;
4390     
4391                   if(rc)
4392                     com_err(whoami, 0, 
4393                             "Unable to set the mailRoutingAddress for %s : %s",
4394                             user_name, ldap_err2string(rc));
4395                 }
4396
4397               while((q = strtok(NULL, ",")) != NULL) {
4398                 StringTrim(q);
4399                 
4400                 if((c = strchr(q, '@')) == NULL) 
4401                   sprintf(temp, "%s@mit.edu", q);
4402                 else
4403                   sprintf(temp, "%s", q);
4404
4405                 if(email_isvalid(temp) && State != US_DELETED) 
4406                   {
4407                     mail_routing_v[0]  = temp;
4408                 
4409                     n = 0;
4410                     ADD_ATTR("mailRoutingAddress", mail_routing_v, 
4411                              LDAP_MOD_ADD);
4412                     mods[n] = NULL;
4413                     rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4414                     
4415                     if (rc == LDAP_ALREADY_EXISTS || 
4416                         rc == LDAP_TYPE_OR_VALUE_EXISTS)
4417                       rc = LDAP_SUCCESS;
4418                     
4419                     if(rc)
4420                       com_err(whoami, 0, 
4421                               "Unable to set the mailRoutingAddress for " 
4422                               "%s : %s",
4423                               user_name, ldap_err2string(rc));
4424                   }
4425               }
4426             } else {
4427               StringTrim(p);
4428
4429             if((c = strchr(p, '@')) == NULL)
4430               sprintf(temp, "%s@mit.edu", p);
4431             else
4432               sprintf(temp, "%s", p);
4433             
4434             if(email_isvalid(temp) && State != US_DELETED) 
4435               {
4436                 mail_routing_v[0]  = temp;
4437                 
4438                 n = 0;
4439                 ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
4440                 mods[n] = NULL;
4441                 rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4442                 
4443                 if (rc == LDAP_ALREADY_EXISTS || 
4444                     rc == LDAP_TYPE_OR_VALUE_EXISTS)
4445                   rc = LDAP_SUCCESS;
4446                 
4447                 if(rc)
4448                   com_err(whoami, 0, 
4449                           "Unable to set the mailRoutingAddress for %s : %s",
4450                           user_name, ldap_err2string(rc));
4451               }
4452             }
4453         } else if(rc==MR_NO_MATCH) {
4454           
4455           n = 0;
4456           ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_REPLACE);
4457           mods[n] = NULL;
4458           rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4459           
4460           if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
4461             rc = LDAP_SUCCESS;
4462
4463           if(rc)
4464             com_err(whoami, 0, 
4465                     "Unable to set the mailRoutingAddress for %s : %s",
4466                     user_name, ldap_err2string(rc));
4467         }
4468       moira_disconnect();
4469     }
4470
4471   if ((strlen(MitId) != 0) && (MitId[0] == '9'))
4472     rc = attribute_update(ldap_handle, distinguished_name, MitId, 
4473                           "employeeID", user_name);
4474   else
4475     rc = attribute_update(ldap_handle, distinguished_name, "none", 
4476                           "employeeID", user_name);
4477
4478   if(strlen(first)) {
4479     strcat(displayName, first);
4480   }
4481
4482   if(strlen(middle)) {
4483     if(strlen(first)) 
4484       strcat(displayName, " ");
4485
4486     strcat(displayName, middle);
4487   }
4488
4489   if(strlen(last)) {
4490     if(strlen(middle) || strlen(first))
4491       strcat(displayName, " ");
4492
4493     strcat(displayName, last);
4494   }
4495
4496   if(strlen(displayName))
4497     rc = attribute_update(ldap_handle, distinguished_name, displayName, 
4498                           "displayName", user_name);
4499   else
4500     rc = attribute_update(ldap_handle, distinguished_name, user_name,
4501                           "displayName", user_name);
4502
4503   if(!ActiveDirectory)
4504     {
4505       if(strlen(displayName))
4506         rc = attribute_update(ldap_handle, distinguished_name, displayName, 
4507                               "cn", user_name);
4508       else
4509         rc = attribute_update(ldap_handle, distinguished_name, user_name,
4510                               "cn", user_name);
4511     }
4512
4513   if(!ActiveDirectory)
4514     {
4515       rc = attribute_update(ldap_handle, distinguished_name, displayName, 
4516                             "eduPersonNickname", user_name);
4517     }
4518
4519   if(strlen(first))
4520     rc = attribute_update(ldap_handle, distinguished_name, first, 
4521                           "givenName", user_name);
4522   else
4523     rc = attribute_update(ldap_handle, distinguished_name, "",
4524                           "givenName", user_name);
4525
4526   if(strlen(middle) == 1) 
4527     rc = attribute_update(ldap_handle, distinguished_name, middle,
4528                           "initials", user_name);
4529   else 
4530     rc = attribute_update(ldap_handle, distinguished_name, "",
4531                           "initials", user_name);
4532   
4533   if(strlen(last))
4534     rc = attribute_update(ldap_handle, distinguished_name, last,
4535                           "sn", user_name);
4536   else 
4537     rc = attribute_update(ldap_handle, distinguished_name, "",
4538                           "sn", user_name);
4539
4540   if(ActiveDirectory)
4541     {
4542       rc = attribute_update(ldap_handle, distinguished_name, Uid, "uid", 
4543                             user_name);
4544     }
4545   else
4546     {
4547       rc = attribute_update(ldap_handle, distinguished_name, user_name, "uid", 
4548                             user_name);
4549     }
4550     
4551   rc = attribute_update(ldap_handle, distinguished_name, MoiraId, 
4552                         "mitMoiraId", user_name);
4553
4554   n = 0;
4555   uid_v[0] = Uid;
4556
4557   if(ActiveDirectory)
4558     {
4559       if (!UseSFU30)
4560         {
4561           ADD_ATTR("uidNumber", uid_v, LDAP_MOD_REPLACE);
4562         }
4563       else
4564         {
4565           ADD_ATTR("msSFU30UidNumber", uid_v, LDAP_MOD_REPLACE);
4566         }
4567     }
4568   else
4569     {
4570       sprintf(principal, "%s@%s", user_name, PRIMARY_REALM);
4571       sprintf(status, "%d", State);
4572       principal_v[0] = principal;
4573       loginshell_v[0] = shell;
4574       mitMoiraClass_v[0] = class;
4575       mitMoiraStatus_v[0] = status;
4576       gid_v[0] = "101";
4577       ADD_ATTR("uidNumber", uid_v, LDAP_MOD_REPLACE);
4578       ADD_ATTR("gidNumber", gid_v, LDAP_MOD_REPLACE);
4579       ADD_ATTR("loginShell", loginshell_v, LDAP_MOD_REPLACE);
4580       ADD_ATTR("eduPersonPrincipalName", mail_v, LDAP_MOD_REPLACE);
4581       ADD_ATTR("mitMoiraClass", mitMoiraClass_v, LDAP_MOD_REPLACE);
4582       ADD_ATTR("mitMoiraStatus", mitMoiraStatus_v, LDAP_MOD_REPLACE);
4583     }
4584
4585   if ((State != US_NO_PASSWD) && (State != US_REGISTERED))
4586     {
4587       userAccountControl |= UF_ACCOUNTDISABLE;
4588
4589       if (Exchange)
4590         {
4591           hide_address_lists_v[0] = "TRUE";
4592           ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
4593                    LDAP_MOD_REPLACE);
4594         }
4595     }
4596   else
4597     {
4598       if (Exchange)
4599         {
4600           hide_address_lists_v[0] = NULL;
4601           address_book_v[0] = address_book;
4602           ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
4603                    LDAP_MOD_REPLACE);
4604
4605           /*
4606           sprintf(address_book, "%s%s", GLOBAL_ADDRESS_LIST_PREFIX, dn_path);
4607           address_book_v[0] = strdup(address_book);
4608           memset(address_book, '\0', sizeof(address_book));
4609           sprintf(address_book, "%s%s", ADDRESS_LIST_PREFIX, dn_path);
4610           address_book_v[1] = strdup(address_book);
4611           memset(address_book, '\0', sizeof(address_book));
4612           sprintf(address_book, "%s%s", EMAIL_ADDRESS_LIST_PREFIX, dn_path);
4613           address_book_v[2] = strdup(address_book);
4614           memset(address_book, '\0', sizeof(address_book));
4615           sprintf(address_book, "%s%s", ALL_ADDRESS_LIST_PREFIX, dn_path);
4616           address_book_v[3] = strdup(address_book);
4617           memset(address_book, '\0', sizeof(address_book));
4618           
4619           ADD_ATTR("showInAddressBook", address_book_v,
4620                    LDAP_MOD_REPLACE);
4621           */
4622         }
4623     }
4624
4625   sprintf(userAccountControlStr, "%ld", userAccountControl);
4626   userAccountControl_v[0] = userAccountControlStr;
4627   ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_REPLACE);
4628
4629   if (Exchange)
4630     {
4631       if (rc = moira_connect())
4632         {
4633           critical_alert("Ldap incremental", 
4634                          "Error contacting Moira server : %s",
4635                          error_message(rc));
4636           return;
4637         }
4638  
4639       argv[0] = user_name;
4640
4641       if (!(rc = mr_query("get_pobox", 1, argv, save_query_info, save_argv)))
4642         {
4643           if(!strcmp(save_argv[1], "EXCHANGE") || 
4644              (strstr(save_argv[3], search_string) != NULL))
4645             {
4646               alt_recipient_v[0] = NULL;
4647               ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_REPLACE);
4648
4649               argv[0] = exchange_acl;
4650               argv[1] = "USER";
4651               argv[2] = user_name;
4652               
4653               rc = mr_query("add_member_to_list", 3, argv, NULL, NULL);
4654               
4655               if ((rc) && (rc != MR_EXISTS))
4656                 {
4657                   com_err(whoami, 0, "Unable to add user %s to %s: %s",
4658                           user_name, exchange_acl, error_message(rc));
4659                 }
4660
4661               if(!strcmp(save_argv[1], "SPLIT") || 
4662                  !strcmp(save_argv[1], "SMTP")) {
4663
4664                 deliver_and_redirect_v[0] = "TRUE";
4665                 alt_recipient_v[0] = alt_recipient;
4666                 ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_REPLACE);
4667                 ADD_ATTR("deliverAndRedirect", deliver_and_redirect_v,
4668                          LDAP_MOD_REPLACE);
4669               }
4670             }
4671           else 
4672             {
4673               deliver_and_redirect_v[0] = "FALSE";
4674               alt_recipient_v[0] = alt_recipient;
4675               ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_REPLACE);
4676               ADD_ATTR("deliverAndRedirect", deliver_and_redirect_v,
4677                        LDAP_MOD_REPLACE);
4678               
4679               argv[0] = exchange_acl;
4680               argv[1] = "USER";
4681               argv[2] = user_name;
4682               
4683               rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL);
4684               
4685               if ((rc) && (rc != MR_NO_MATCH))
4686                 {  
4687                   com_err(whoami, 0,
4688                           "Unable to remove user %s from %s: %s, %d",
4689                           user_name, exchange_acl, error_message(rc), rc);
4690                 }  
4691             }
4692         }
4693       else
4694         {
4695           deliver_and_redirect_v[0] = "FALSE";
4696           alt_recipient_v[0] = alt_recipient;
4697           ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_REPLACE);
4698           ADD_ATTR("deliverAndRedirect", deliver_and_redirect_v,
4699                    LDAP_MOD_REPLACE);     
4700
4701           argv[0] = exchange_acl;
4702           argv[1] = "USER";
4703           argv[2] = user_name;
4704           
4705           rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL);
4706           
4707           if ((rc) && (rc != MR_NO_MATCH))
4708             {  
4709               com_err(whoami, 0,
4710                       "Unable to remove user %s from %s: %s, %d",
4711                       user_name, exchange_acl, error_message(rc), rc);
4712             }  
4713         }
4714       
4715       moira_disconnect();
4716     }
4717   else
4718     {
4719       mail_v[0] = contact_mail;
4720       ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
4721
4722       if(!ActiveDirectory)
4723         {
4724           ADD_ATTR("mitMoiraMail", mail_v, LDAP_MOD_REPLACE);
4725         }
4726     }
4727
4728   n = SetHomeDirectory(ldap_handle, user_name, distinguished_name, WinHomeDir, 
4729                        WinProfileDir, homedir_v, winProfile_v,
4730                        drives_v, mods, LDAP_MOD_REPLACE, n);
4731
4732   if(ActiveDirectory)
4733     {
4734       sprintf(filter_exp, "(sAMAccountName=%s)", "UserTemplate.u");
4735       sprintf(search_path, "%s,%s", security_template_ou, dn_path);
4736       attr_array[0] = "sAMAccountName";
4737       attr_array[1] = NULL;
4738       group_count = 0;
4739       group_base = NULL;
4740     
4741       if ((rc = linklist_build(ldap_handle, search_path, filter_exp, 
4742                                attr_array,
4743                                &group_base, &group_count, 
4744                                LDAP_SCOPE_SUBTREE) != 0))
4745         return(1);
4746       
4747       if (group_count != 1)
4748         {
4749           com_err(whoami, 0, "Unable to process user security template: %s - "
4750                   "security not set", "UserTemplate.u");
4751           return(1);
4752         }
4753
4754       strcpy(TemplateDn, group_base->dn);
4755       strcpy(TemplateSamName, group_base->value);
4756       linklist_free(group_base);
4757       group_base = NULL;
4758       group_count = 0;
4759       
4760       rc = ldap_search_ext_s(ldap_handle, search_path, LDAP_SCOPE_SUBTREE,
4761                              filter_exp, NULL, 0, apsServerControls, NULL,
4762                              NULL, 0, &psMsg);
4763
4764       if ((psMsg = ldap_first_entry(ldap_handle, psMsg)) == NULL)
4765         {
4766           com_err(whoami, 0, "Unable to find user security template: %s - "
4767                   "security not set", "UserTemplate.u");
4768           return(1);
4769         }
4770       
4771       ppsValues = ldap_get_values_len(ldap_handle, psMsg, 
4772                                       "ntSecurityDescriptor");
4773
4774       if (ppsValues == NULL)
4775         {
4776           com_err(whoami, 0, "Unable to find user security template: %s - "
4777                   "security not set", "UserTemplate.u");
4778           return(1);
4779         }
4780       
4781       ADD_ATTR("ntSecurityDescriptor", (char **)ppsValues,
4782                LDAP_MOD_REPLACE | LDAP_MOD_BVALUES);
4783     }
4784
4785   mods[n] = NULL;
4786
4787   if ((rc = ldap_modify_s(ldap_handle, distinguished_name, 
4788                           mods)) != LDAP_SUCCESS)
4789     {
4790       OldUseSFU30 = UseSFU30;
4791       SwitchSFU(mods, &UseSFU30, n);
4792       if (OldUseSFU30 != UseSFU30)
4793         rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4794       if (rc)
4795         {
4796           com_err(whoami, 0, "Unable to modify user data for %s : %s",
4797                   user_name, ldap_err2string(rc));
4798         }
4799     }
4800   
4801   for (i = 0; i < n; i++)
4802     free(mods[i]);
4803
4804   return(rc);
4805 }
4806
4807 int user_rename(LDAP *ldap_handle, char *dn_path, char *before_user_name, 
4808                 char *user_name)
4809 {
4810   LDAPMod *mods[20];
4811   char new_dn[256];
4812   char old_dn[256];
4813   char upn[256];
4814   char mail[256];
4815   char contact_mail[256];
4816   char proxy_address[256];
4817   char query_base_dn[256];
4818   char temp[256];
4819   char *userPrincipalName_v[] = {NULL, NULL};
4820   char *altSecurityIdentities_v[] = {NULL, NULL};
4821   char *name_v[] = {NULL, NULL};
4822   char *samAccountName_v[] = {NULL, NULL};
4823   char *mail_v[] = {NULL, NULL};
4824   char *mail_nickname_v[] = {NULL, NULL};
4825   char *proxy_address_v[] = {NULL, NULL};
4826   char *query_base_dn_v[] = {NULL, NULL};
4827   char *principal_v[] = {NULL, NULL};
4828   char principal[256];
4829   int  n;
4830   int  rc;
4831   int  i;
4832
4833   if (!check_string(before_user_name))
4834     {
4835       com_err(whoami, 0, 
4836               "Unable to process invalid LDAP user name %s", before_user_name);
4837       return(AD_INVALID_NAME);
4838     }
4839
4840   if (!check_string(user_name))
4841     {
4842       com_err(whoami, 0, 
4843               "Unable to process invalid LDAP user name %s", user_name);
4844       return(AD_INVALID_NAME);
4845     }
4846
4847   strcpy(user_name, user_name);
4848  
4849   if(ActiveDirectory)
4850     sprintf(old_dn, "cn=%s,%s,%s", before_user_name, user_ou, dn_path);
4851   else
4852     sprintf(old_dn, "uid=%s,%s,%s", before_user_name, user_ou, dn_path);
4853
4854   if(ActiveDirectory)
4855     sprintf(new_dn, "cn=%s", user_name);
4856   else
4857     sprintf(new_dn, "uid=%s", user_name);
4858
4859   sprintf(mail, "%s@%s", user_name, lowercase(ldap_domain));
4860   sprintf(contact_mail, "%s@mit.edu", user_name);
4861   sprintf(proxy_address, "SMTP:%s@%s", user_name, lowercase(ldap_domain)); 
4862   sprintf(principal, "%s@%s", user_name, PRIMARY_REALM);
4863
4864   if ((rc = ldap_rename_s(ldap_handle, old_dn, new_dn, NULL, TRUE, 
4865                            NULL, NULL)) != LDAP_SUCCESS)
4866     {
4867       com_err(whoami, 0, "Unable to rename user from %s to %s : %s",
4868               before_user_name, user_name, ldap_err2string(rc));
4869       return(rc);
4870     }
4871
4872   if (Exchange)
4873     {
4874       sprintf(temp, "cn=%s@mit.edu,%s,%s", before_user_name, contact_ou, 
4875               dn_path);
4876
4877       if(rc = ldap_delete_s(ldap_handle, temp))
4878         {
4879           com_err(whoami, 0, "Unable to delete user contact for %s",
4880                   user_name);
4881         }
4882       
4883       if(contact_create(ldap_handle, dn_path, contact_mail, contact_ou))
4884         {
4885           com_err(whoami, 0, "Unable to create user contact %s", contact_mail);
4886         }
4887     }
4888
4889   name_v[0] = user_name;
4890   sprintf(upn, "%s@%s", user_name, ldap_domain);
4891   userPrincipalName_v[0] = upn;
4892   principal_v[0] = principal;
4893   sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
4894   sprintf(query_base_dn, "%s%s", ADDRESS_LIST_PREFIX, dn_path);
4895   altSecurityIdentities_v[0] = temp;
4896   samAccountName_v[0] = user_name;
4897   mail_v[0] = mail;
4898   mail_nickname_v[0] = user_name;
4899   proxy_address_v[0] = proxy_address; 
4900   query_base_dn_v[0] = query_base_dn;
4901
4902   n = 0;
4903   ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_REPLACE);
4904   ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_REPLACE);
4905   ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
4906   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_REPLACE);
4907
4908   if(!ActiveDirectory)
4909     {
4910       ADD_ATTR("uid", samAccountName_v, LDAP_MOD_REPLACE);
4911       ADD_ATTR("eduPersonPrincipalName", mail_v, LDAP_MOD_REPLACE);
4912       ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
4913       ADD_ATTR("eduPersonNickname", name_v, LDAP_MOD_REPLACE);
4914     }
4915
4916   if (Exchange)
4917     {
4918       ADD_ATTR("msExchQueryBaseDN", query_base_dn_v, LDAP_MOD_REPLACE);
4919       ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_REPLACE); 
4920       ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE); 
4921       ADD_ATTR("proxyAddresses", proxy_address_v, LDAP_MOD_REPLACE);
4922     }
4923   else
4924     {
4925       mail_v[0] = contact_mail;
4926       ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE); 
4927
4928       if(!ActiveDirectory)
4929         {
4930           ADD_ATTR("mitMoiraMail", mail_v, LDAP_MOD_REPLACE);
4931         }
4932     }
4933
4934   mods[n] = NULL;
4935   
4936   if(ActiveDirectory)
4937     sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, dn_path);
4938   else
4939     sprintf(new_dn, "uid=%s,%s,%s", user_name, user_ou, dn_path);
4940
4941   if ((rc = ldap_modify_s(ldap_handle, new_dn, mods)) != LDAP_SUCCESS)
4942     {
4943       com_err(whoami, 0, 
4944               "Unable to modify user data for %s after renaming : %s",
4945               user_name, ldap_err2string(rc));
4946     }
4947   
4948   for (i = 0; i < n; i++)
4949     free(mods[i]);
4950
4951   return(rc);
4952 }
4953
4954 int user_create(int ac, char **av, void *ptr)
4955 {
4956   LDAPMod *mods[20];
4957   char new_dn[256];
4958   char user_name[256];
4959   char sam_name[256];
4960   char upn[256];
4961   char mail[256];
4962   char contact_mail[256];
4963   char proxy_address[256];
4964   char mail_nickname[256];
4965   char query_base_dn[256];
4966   char displayName[256];
4967   char address_book[1024];
4968   char alt_recipient[256];
4969   char filesys_name[256];
4970   char *cn_v[] = {NULL, NULL};
4971   char *objectClass_v[] = {"top", "person", "organizationalPerson",
4972                            "user", NULL};
4973   char *objectClass_ldap_v[] = {"top", 
4974                                 "eduPerson", "posixAccount", 
4975                                 "apple-user", "shadowAccount",
4976                                 "microsoftComTop", "securityPrincipal",
4977                                 "inetOrgPerson", "user", 
4978                                 "organizationalPerson", "person",
4979                                 "mailRecipient", NULL};
4980
4981   char *samAccountName_v[] = {NULL, NULL};
4982   char *altSecurityIdentities_v[] = {NULL, NULL};
4983   char *mitMoiraId_v[] = {NULL, NULL};
4984   char *mitMoiraClass_v[] = {NULL, NULL};
4985   char *mitMoiraStatus_v[] = {NULL, NULL};
4986   char *name_v[] = {NULL, NULL};
4987   char *desc_v[] = {NULL, NULL};
4988   char *userPrincipalName_v[] = {NULL, NULL};
4989   char *userAccountControl_v[] = {NULL, NULL};
4990   char *uid_v[] = {NULL, NULL};
4991   char *gid_v[] = {NULL, NULL};
4992   char *mitid_v[] = {NULL, NULL};
4993   char *homedir_v[] = {NULL, NULL};
4994   char *winProfile_v[] = {NULL, NULL};
4995   char *drives_v[] = {NULL, NULL};
4996   char *mail_v[] = {NULL, NULL};
4997   char *givenName_v[] = {NULL, NULL};
4998   char *sn_v[] = {NULL, NULL};
4999   char *initials_v[] = {NULL, NULL};
5000   char *displayName_v[] = {NULL, NULL};
5001   char *proxy_address_v[] = {NULL, NULL};
5002   char *mail_nickname_v[] = {NULL, NULL};
5003   char *query_base_dn_v[] = {NULL, NULL};
5004   char *address_book_v[] = {NULL, NULL, NULL, NULL, NULL};
5005   char *homeMDB_v[] = {NULL, NULL};
5006   char *homeServerName_v[] = {NULL, NULL};
5007   char *mdbUseDefaults_v[] = {NULL, NULL};
5008   char *mailbox_guid_v[] = {NULL, NULL};
5009   char *user_culture_v[] = {NULL, NULL};
5010   char *user_account_control_v[] = {NULL, NULL};
5011   char *msexch_version_v[] = {NULL, NULL};
5012   char *alt_recipient_v[] = {NULL, NULL};
5013   char *hide_address_lists_v[] = {NULL, NULL};
5014   char *principal_v[] = {NULL, NULL};
5015   char *loginshell_v[] = {NULL, NULL};
5016   char userAccountControlStr[80];
5017   char temp[1024];
5018   char principal[256];
5019   char filter_exp[1024];
5020   char search_path[512];
5021   char *attr_array[3];
5022   u_int userAccountControl = UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD | 
5023     UF_PASSWD_CANT_CHANGE; 
5024   int  n;
5025   int  rc;
5026   int  i;
5027   int  OldUseSFU30;
5028   char **call_args;
5029   char WinHomeDir[1024];
5030   char WinProfileDir[1024];
5031   char *homeMDB;
5032   char *homeServerName;
5033   ULONG dwInfo;
5034   char acBERBuf[N_SD_BER_BYTES];
5035   LK_ENTRY  *group_base;
5036   int    group_count;
5037   char TemplateDn[512];
5038   char TemplateSamName[128];
5039   LDAP_BERVAL **ppsValues;
5040   LDAPControl sControl = {"1.2.840.113556.1.4.801",
5041                           { N_SD_BER_BYTES, acBERBuf },
5042                           TRUE};
5043   LDAPControl *apsServerControls[] = {&sControl, NULL};
5044   LDAPMessage *psMsg;
5045   char *argv[3];
5046   char *save_argv[7];
5047   char search_string[256];
5048   char *o_v[] = {NULL, NULL};
5049   char *p, *q;
5050   char *mail_routing_v[] = {NULL, NULL};
5051   char *mail_alternate_v[] = {NULL, NULL};
5052   char *mit_moira_imap_address_v[] = {NULL, NULL};
5053   char *deliver_and_redirect_v[] = {NULL, NULL};
5054   char *c;
5055
5056   call_args = ptr;
5057
5058   dwInfo = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
5059     DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;
5060   BEREncodeSecurityBits(dwInfo, acBERBuf);
5061
5062   if (!check_string(av[U_NAME]))
5063     {
5064       callback_rc = AD_INVALID_NAME;
5065       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", 
5066               av[U_NAME]);
5067       return(AD_INVALID_NAME);
5068     }
5069
5070   memset(WinHomeDir, '\0', sizeof(WinHomeDir));
5071   memset(WinProfileDir, '\0', sizeof(WinProfileDir));
5072   memset(displayName, '\0', sizeof(displayName));
5073   memset(query_base_dn, '\0', sizeof(query_base_dn));
5074   memset(filesys_name, '\0', sizeof(filesys_name));
5075   strcpy(WinHomeDir, av[U_WINHOMEDIR]);
5076   strcpy(WinProfileDir, av[U_WINPROFILEDIR]);
5077   strcpy(user_name, av[U_NAME]);
5078   sprintf(upn, "%s@%s", user_name, ldap_domain);
5079   sprintf(sam_name, "%s", av[U_NAME]);
5080   sprintf(filesys_name, "%s.po", user_name);
5081
5082   if(strlen(av[U_FIRST])) {
5083     strcat(displayName, av[U_FIRST]);
5084   }
5085
5086   if(strlen(av[U_MIDDLE])) {
5087     if(strlen(av[U_FIRST]))
5088        strcat(displayName, " "); 
5089   
5090     strcat(displayName, av[U_MIDDLE]);
5091   }
5092
5093   if(strlen(av[U_LAST])) {
5094     if(strlen(av[U_FIRST]) || strlen(av[U_MIDDLE]))
5095       strcat(displayName, " ");
5096
5097     strcat(displayName, av[U_LAST]);
5098   }
5099
5100   samAccountName_v[0] = sam_name;
5101   if ((atoi(av[U_STATE]) != US_NO_PASSWD) && 
5102       (atoi(av[U_STATE]) != US_REGISTERED))
5103     {
5104       userAccountControl |= UF_ACCOUNTDISABLE;
5105
5106       if (Exchange)
5107         {
5108           hide_address_lists_v[0] = "TRUE";
5109
5110           ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
5111                    LDAP_MOD_ADD);
5112
5113           /*
5114           sprintf(address_book, "%s%s", GLOBAL_ADDRESS_LIST_PREFIX, 
5115                   call_args[1]);
5116           address_book_v[0] = strdup(address_book);
5117           memset(address_book, '\0', sizeof(address_book));
5118           sprintf(address_book, "%s%s", ADDRESS_LIST_PREFIX, call_args[1]);
5119           address_book_v[1] = strdup(address_book);
5120           memset(address_book, '\0', sizeof(address_book));
5121           sprintf(address_book, "%s%s", EMAIL_ADDRESS_LIST_PREFIX, 
5122                   call_args[1]);
5123           address_book_v[2] = strdup(address_book);
5124           memset(address_book, '\0', sizeof(address_book));
5125           sprintf(address_book, "%s%s", ALL_ADDRESS_LIST_PREFIX, 
5126                   call_args[1]);
5127           address_book_v[3] = strdup(address_book);
5128           memset(address_book, '\0', sizeof(address_book));
5129           
5130           ADD_ATTR("showInAddressBook", address_book_v,
5131                    LDAP_MOD_ADD);
5132           */
5133         }
5134     }
5135
5136   sprintf(userAccountControlStr, "%ld", userAccountControl);
5137   userAccountControl_v[0] = userAccountControlStr;
5138   userPrincipalName_v[0] = upn;
5139   
5140   if(ActiveDirectory)
5141     cn_v[0] = user_name;
5142   else
5143     cn_v[0] = displayName;
5144     
5145   name_v[0] = user_name;
5146   desc_v[0] = "Auto account created by Moira";
5147   mail_v[0] = mail;
5148   givenName_v[0] = av[U_FIRST];
5149
5150   if(ActiveDirectory)
5151     sn_v[0] = av[U_LAST];
5152   else
5153     if(strlen(av[U_LAST]))
5154       sn_v[0] = av[U_LAST];
5155     else
5156       sn_v[0] = av[U_NAME];
5157
5158   displayName_v[0] = displayName;
5159   mail_nickname_v[0] = user_name;
5160   o_v[0] = "Massachusetts Institute of Technology";
5161
5162   sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
5163   sprintf(principal, "%s@%s", user_name, PRIMARY_REALM);
5164   altSecurityIdentities_v[0] = temp;    
5165   principal_v[0] = principal;
5166
5167   if(ActiveDirectory)
5168     sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, call_args[1]);
5169   else
5170     sprintf(new_dn, "uid=%s,%s,%s", user_name, user_ou, call_args[1]);
5171
5172   sprintf(mail,"%s@%s", user_name, lowercase(ldap_domain));
5173   if(Exchange)
5174     sprintf(contact_mail, "%s@exchange-forwarding.mit.edu", user_name);
5175   else
5176     sprintf(contact_mail, "%s@mit.edu", user_name);    
5177   sprintf(query_base_dn, "%s%s", ADDRESS_LIST_PREFIX, call_args[1]);
5178   query_base_dn_v[0] = query_base_dn;
5179   sprintf(alt_recipient, "cn=%s@exchange-forwarding.mit.edu,%s,%s", user_name,
5180           contact_ou, call_args[1]);
5181   sprintf(search_string, "@%s", uppercase(ldap_domain));
5182
5183   if (Exchange)
5184     {
5185       if(contact_create((LDAP *)call_args[0], call_args[1], contact_mail, 
5186                         contact_ou))
5187         {
5188           com_err(whoami, 0, "Unable to create user contact %s", 
5189                   contact_mail);
5190         }
5191       
5192       if(find_homeMDB((LDAP *)call_args[0], call_args[1], &homeMDB, 
5193                       &homeServerName)) 
5194         {
5195           com_err(whoami, 0, "Unable to locate homeMB and homeServerName");
5196           return(1);
5197         }
5198       
5199       com_err(whoami, 0, "homeMDB:%s", homeMDB);
5200       com_err(whoami, 0, "homeServerName:%s", homeServerName);
5201   
5202       homeMDB_v[0] = homeMDB;
5203       homeServerName_v[0] = homeServerName; 
5204     }
5205
5206   n = 0;
5207
5208   ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
5209   
5210   if(ActiveDirectory) 
5211     {
5212       ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
5213     }
5214   else
5215     {
5216       ADD_ATTR("objectClass", objectClass_ldap_v, LDAP_MOD_ADD);
5217     }
5218
5219   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
5220   ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_ADD);
5221   ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_ADD);
5222   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
5223   ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
5224
5225   if (Exchange)
5226     {
5227       ADD_ATTR("msExchQueryBaseDN", query_base_dn_v, LDAP_MOD_ADD);
5228       ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_ADD);
5229       ADD_ATTR("homeMDB", homeMDB_v, LDAP_MOD_ADD);
5230       mdbUseDefaults_v[0] = "TRUE";
5231       ADD_ATTR("mdbUseDefaults", mdbUseDefaults_v, LDAP_MOD_ADD);
5232       ADD_ATTR("msExchHomeServerName", homeServerName_v, LDAP_MOD_ADD); 
5233       
5234       argv[0] = user_name;
5235     
5236       if (!(rc = mr_query("get_pobox", 1, argv, save_query_info, save_argv)))
5237         {
5238           if(!strcmp(save_argv[1], "EXCHANGE") || 
5239              (strstr(save_argv[3], search_string) != NULL))
5240             {
5241               argv[0] = exchange_acl;
5242               argv[1] = "USER";
5243               argv[2] = user_name;
5244               
5245               rc = mr_query("add_member_to_list", 3, argv, NULL, NULL);
5246               
5247               if ((rc) && (rc != MR_EXISTS))
5248                 {
5249                   com_err(whoami, 0, "Unable to add user %s to %s: %s",
5250                           user_name, exchange_acl, error_message(rc));
5251                 }
5252
5253               if(!strcmp(save_argv[1], "SPLIT") ||
5254                  !strcmp(save_argv[1], "SMTP")) {
5255                 
5256                 deliver_and_redirect_v[0] = "TRUE";
5257                 alt_recipient_v[0] = alt_recipient;
5258
5259                 ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_ADD);
5260                 ADD_ATTR("deliverAndRedirect", deliver_and_redirect_v,
5261                          LDAP_MOD_ADD);
5262               }
5263             }
5264           else 
5265             {
5266               alt_recipient_v[0] = alt_recipient;
5267               ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_ADD);
5268             }
5269         }
5270       else
5271         {
5272           alt_recipient_v[0] = alt_recipient;
5273           ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_ADD);
5274           
5275           com_err(whoami, 0, "Unable to fetch pobox for %s", user_name);
5276         }
5277     }
5278   else
5279     {
5280       mail_v[0] = contact_mail;
5281       ADD_ATTR("mail", mail_v, LDAP_MOD_ADD);
5282
5283       if(!ActiveDirectory)
5284         {
5285           ADD_ATTR("mitMoiraMail", mail_v, LDAP_MOD_ADD);
5286         }
5287     }
5288
5289   if(strlen(av[U_FIRST])) {
5290     ADD_ATTR("givenName", givenName_v, LDAP_MOD_ADD);
5291   }
5292
5293   if(strlen(av[U_LAST]) || strlen(av[U_NAME])) {
5294     ADD_ATTR("sn", sn_v, LDAP_MOD_ADD);
5295   }
5296
5297   if(strlen(av[U_FIRST]) || strlen(av[U_MIDDLE]) || strlen(av[U_LAST])) {
5298     ADD_ATTR("displayName", displayName_v, LDAP_MOD_ADD);
5299
5300     if(!ActiveDirectory)
5301       {
5302         ADD_ATTR("eduPersonNickname", displayName_v, LDAP_MOD_ADD);      
5303       }
5304   } else {
5305     ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
5306
5307     if(!ActiveDirectory)
5308       {
5309         ADD_ATTR("eduPersonNickname", name_v, LDAP_MOD_ADD);            
5310       }
5311   }
5312
5313   if (strlen(av[U_MIDDLE]) == 1) {
5314     initials_v[0] = av[U_MIDDLE];
5315     ADD_ATTR("initials", initials_v, LDAP_MOD_ADD);
5316   }
5317
5318   if (strlen(call_args[2]) != 0)    
5319     {
5320       mitMoiraId_v[0] = call_args[2];
5321       ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_ADD); 
5322     }
5323
5324   ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_ADD);
5325
5326   if(!ActiveDirectory)
5327     {
5328       loginshell_v[0] = av[U_SHELL];
5329       mitMoiraClass_v[0] = av[U_CLASS];
5330       mitMoiraStatus_v[0] = av[U_STATE];
5331       ADD_ATTR("loginShell", loginshell_v, LDAP_MOD_ADD);
5332       ADD_ATTR("uid", samAccountName_v, LDAP_MOD_ADD);
5333       ADD_ATTR("eduPersonPrincipalName", mail_v, LDAP_MOD_ADD);
5334       ADD_ATTR("o", o_v, LDAP_MOD_ADD);
5335       ADD_ATTR("mitMoiraClass", mitMoiraClass_v, LDAP_MOD_ADD);
5336       ADD_ATTR("mitMoiraStatus", mitMoiraStatus_v, LDAP_MOD_ADD);
5337     }
5338
5339   if (strlen(av[U_UID]) != 0)
5340     {
5341       uid_v[0] = av[U_UID];
5342
5343       if(ActiveDirectory) 
5344         {
5345           ADD_ATTR("uid", uid_v, LDAP_MOD_ADD);
5346         }
5347       else
5348         {
5349           gid_v[0] = "101";
5350           ADD_ATTR("uidNumber", uid_v, LDAP_MOD_ADD);
5351           ADD_ATTR("gidNumber", gid_v, LDAP_MOD_ADD);
5352         }
5353
5354       if(ActiveDirectory)
5355         {
5356           if (!UseSFU30)
5357             {
5358               ADD_ATTR("uidNumber", uid_v, LDAP_MOD_ADD);
5359             }
5360           else
5361             {
5362               ADD_ATTR("msSFU30UidNumber", uid_v, LDAP_MOD_ADD);
5363             }
5364         }
5365     }
5366
5367   if ((strlen(av[U_MITID]) != 0) && (av[U_MITID][0] == '9'))
5368       mitid_v[0] = av[U_MITID];
5369   else
5370       mitid_v[0] = "none";
5371
5372   ADD_ATTR("employeeID", mitid_v, LDAP_MOD_ADD);
5373
5374   n = SetHomeDirectory((LDAP *)call_args[0], user_name, new_dn, 
5375                        WinHomeDir, WinProfileDir, homedir_v, winProfile_v,
5376                        drives_v, mods, LDAP_MOD_ADD, n);
5377   
5378   if(ActiveDirectory) 
5379     {
5380       sprintf(filter_exp, "(sAMAccountName=%s)", "UserTemplate.u");
5381       sprintf(search_path, "%s,%s", security_template_ou, call_args[1]);
5382       attr_array[0] = "sAMAccountName";
5383       attr_array[1] = NULL;
5384       group_count = 0;
5385       group_base = NULL;
5386       
5387       if ((rc = linklist_build((LDAP *)call_args[0], search_path, filter_exp, 
5388                                attr_array, &group_base, &group_count, 
5389                                LDAP_SCOPE_SUBTREE) != 0))
5390         return(1);
5391       
5392       if (group_count != 1)
5393         {
5394           com_err(whoami, 0, "Unable to process user security template: %s - "
5395                   "security not set", "UserTemplate.u");
5396           return(1);
5397         }
5398       
5399       strcpy(TemplateDn, group_base->dn);
5400       strcpy(TemplateSamName, group_base->value);
5401       linklist_free(group_base);
5402       group_base = NULL;
5403       group_count = 0;
5404       
5405       rc = ldap_search_ext_s((LDAP *)call_args[0], search_path, 
5406                              LDAP_SCOPE_SUBTREE, filter_exp, NULL, 0, 
5407                              apsServerControls, NULL,
5408                              NULL, 0, &psMsg);
5409       
5410       if ((psMsg = ldap_first_entry((LDAP *)call_args[0], psMsg)) == NULL)
5411         {
5412           com_err(whoami, 0, "Unable to find user security template: %s - "
5413                   "security not set", "UserTemplate.u");
5414           return(1);
5415         }
5416       
5417       ppsValues = ldap_get_values_len((LDAP *)call_args[0], psMsg, 
5418                                       "ntSecurityDescriptor");
5419       if (ppsValues == NULL)
5420         {
5421           com_err(whoami, 0, "Unable to find user security template: %s - "
5422                   "security not set", "UserTemplate.u");
5423           return(1);
5424         }
5425       
5426       ADD_ATTR("ntSecurityDescriptor", (char **)ppsValues,
5427                LDAP_MOD_REPLACE | LDAP_MOD_BVALUES); 
5428     }
5429
5430   mods[n] = NULL;
5431
5432   rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
5433
5434   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
5435     {
5436       OldUseSFU30 = UseSFU30;
5437       SwitchSFU(mods, &UseSFU30, n);
5438       if (OldUseSFU30 != UseSFU30)
5439         rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
5440     }
5441
5442   for (i = 0; i < n; i++)
5443     free(mods[i]);
5444
5445   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
5446     {
5447       com_err(whoami, 0, "Unable to create user %s : %s",
5448               user_name, ldap_err2string(rc));
5449       callback_rc = rc;
5450       return(rc);
5451     }
5452
5453   if ((rc == LDAP_SUCCESS) && (SetPassword))
5454     {
5455       if ((rc = set_password(sam_name, "", ldap_domain)) != 0)
5456         {
5457           ad_kdc_disconnect();
5458           if (!ad_server_connect(default_server, ldap_domain))
5459             {
5460               com_err(whoami, 0, "Unable to set password for user %s : %s",
5461                       user_name, 
5462                       "cannot get changepw ticket from windows domain");
5463             }
5464           else
5465             {
5466               if ((rc = set_password(sam_name, "", ldap_domain)) != 0)
5467                 {
5468                   com_err(whoami, 0, "Unable to set password for user %s "
5469                           ": %ld", user_name, rc);
5470                 }
5471             }
5472         }
5473     }
5474
5475   if(!ActiveDirectory) 
5476     {
5477       if (rc = moira_connect())
5478         {
5479           critical_alert("Ldap incremental", 
5480                          "Error contacting Moira server : %s",
5481                          error_message(rc));
5482           return;
5483         }
5484   
5485       argv[0] = filesys_name;
5486
5487       if (!(rc = mr_query("get_filesys_by_label", 1, argv, save_query_info, 
5488                           save_argv)))
5489         {
5490           n = 0;
5491           ADD_ATTR("mitMoiraIMAPAddress", mit_moira_imap_address_v, 
5492                    LDAP_MOD_REPLACE);
5493           mods[n] = NULL;
5494           rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5495           
5496           if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
5497             rc = LDAP_SUCCESS;
5498
5499           if(rc)
5500             com_err(whoami, 0, 
5501                     "Unable to set the mitMoiraIMAPAddress for %s : %s",
5502                     user_name, ldap_err2string(rc));
5503
5504           sprintf(temp, "%s@%s", user_name, save_argv[FS_MACHINE]);
5505           
5506           mit_moira_imap_address_v[0]  = temp;
5507                 
5508           n = 0;
5509           ADD_ATTR("mitMoiraIMAPAddress", mit_moira_imap_address_v, 
5510                    LDAP_MOD_ADD);
5511           mods[n] = NULL;
5512           rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5513           
5514           if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
5515             rc = LDAP_SUCCESS;
5516           
5517           if(rc)
5518             com_err(whoami, 0, "Unable to set the mitMoiraIMAPAddress for " 
5519                     "%s : %s", user_name, ldap_err2string(rc));   
5520         } else if(rc==MR_NO_MATCH) {
5521           
5522           n = 0;
5523           ADD_ATTR("mitMoiraIMAPAddress", mit_moira_imap_address_v, 
5524                    LDAP_MOD_REPLACE);
5525           mods[n] = NULL;
5526           rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5527           
5528           if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
5529             rc = LDAP_SUCCESS;
5530
5531           if(rc)
5532             com_err(whoami, 0, 
5533                     "Unable to set the mitMoiraIMAPAddress for %s : %s",
5534                     user_name, ldap_err2string(rc));
5535
5536         }
5537
5538       argv[0] = user_name;
5539     
5540       if (!(rc = mr_query("get_pobox", 1, argv, save_query_info, save_argv)))
5541         {
5542           n = 0;
5543           ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_REPLACE);
5544           mods[n] = NULL;
5545           rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5546            
5547           if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
5548             rc = LDAP_SUCCESS;
5549
5550           if(rc)
5551             com_err(whoami, 0,
5552                     "Unable to set the mailRoutingAddress for %s : %s",
5553                     user_name, ldap_err2string(rc));
5554
5555           p = strdup(save_argv[3]);
5556           
5557           if((c = strchr(p, ',')) != NULL) {
5558             q = strtok(p, ",");
5559             StringTrim(q);
5560
5561             if ((c = strchr(q, '@')) == NULL)
5562               sprintf(temp, "%s@mit.edu", q);
5563             else
5564               sprintf(temp, "%s", q);
5565
5566             if(email_isvalid(temp) && atoi(av[U_STATE]) != US_DELETED) 
5567               {
5568                 mail_routing_v[0]  = temp;
5569
5570                 n = 0;
5571                 ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
5572                 mods[n] = NULL;
5573                 rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5574                 
5575                 if (rc == LDAP_ALREADY_EXISTS || 
5576                     rc == LDAP_TYPE_OR_VALUE_EXISTS)
5577                   rc = LDAP_SUCCESS;
5578                 
5579                 if(rc)
5580                   com_err(whoami, 0, 
5581                           "Unable to set the mailRoutingAddress for %s : %s",
5582                           user_name, ldap_err2string(rc));
5583               }
5584
5585             while((q = strtok(NULL, ",")) != NULL) {
5586               StringTrim(q);
5587
5588               if((c = strchr(q, '@')) == NULL)
5589                 sprintf(temp, "%s@mit.edu", q);
5590               else
5591                 sprintf(temp, "%s", q);
5592
5593               if(email_isvalid(temp) && atoi(av[U_STATE]) != US_DELETED)
5594                 {
5595                   mail_routing_v[0]  = temp;
5596                   
5597                   n = 0;
5598                   ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
5599                   mods[n] = NULL;
5600                   rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5601                   
5602                   if (rc == LDAP_ALREADY_EXISTS || 
5603                       rc == LDAP_TYPE_OR_VALUE_EXISTS)
5604                     rc = LDAP_SUCCESS;
5605                   
5606                   if(rc)
5607                     com_err(whoami, 0, 
5608                             "Unable to set the mailRoutingAddress for %s : %s",
5609                             user_name, ldap_err2string(rc));
5610                 }
5611             }
5612           } else {
5613             StringTrim(p);
5614
5615             if((c = strchr(p, '@')) == NULL)
5616               sprintf(temp, "%s@mit.edu", p);
5617             else
5618               sprintf(temp, "%s", p);
5619
5620             if(email_isvalid(temp) && atoi(av[U_STATE]) != US_DELETED) 
5621               {
5622                 mail_routing_v[0]  = temp;
5623                 
5624                 n = 0;
5625                 ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
5626                 mods[n] = NULL;
5627                 rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5628                 
5629                 if (rc == LDAP_ALREADY_EXISTS || 
5630                     rc == LDAP_TYPE_OR_VALUE_EXISTS)
5631                   rc = LDAP_SUCCESS;
5632                 
5633                 if(rc)
5634                   com_err(whoami, 0, 
5635                           "Unable to set the mailRoutingAddress for %s : %s",
5636                           user_name, ldap_err2string(rc));
5637               }
5638           }
5639         }
5640       moira_disconnect();
5641     }
5642
5643   return(0);
5644 }
5645
5646 int user_change_status(LDAP *ldap_handle, char *dn_path, 
5647                        char *user_name, char *MoiraId,
5648                        int operation)
5649 {
5650   char      filter[128];
5651   char      *attr_array[3];
5652   char      temp[256];
5653   char      distinguished_name[1024];
5654   char      **modvalues;
5655   char      *mitMoiraId_v[] = {NULL, NULL};
5656   LDAPMod   *mods[20];
5657   LK_ENTRY  *group_base;
5658   int       group_count;
5659   int       rc;
5660   int       i;
5661   int       n;
5662   ULONG     ulongValue;
5663
5664   if (!check_string(user_name))
5665     {
5666       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", 
5667               user_name);
5668       return(AD_INVALID_NAME);
5669     }
5670
5671   group_count = 0;
5672   group_base = NULL;
5673
5674   if (strlen(MoiraId) != 0)
5675     {
5676       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
5677       attr_array[0] = "UserAccountControl";
5678       attr_array[1] = NULL;
5679       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
5680                                &group_base, &group_count, 
5681                                LDAP_SCOPE_SUBTREE)) != 0)
5682         {
5683           com_err(whoami, 0, "Unable to process user %s : %s",
5684                   user_name, ldap_err2string(rc));
5685           return(rc);
5686         }
5687     }
5688
5689   if (group_count != 1)
5690     {
5691       linklist_free(group_base);
5692       group_count = 0;
5693       group_base = NULL;
5694       sprintf(filter, "(sAMAccountName=%s)", user_name);
5695       attr_array[0] = "UserAccountControl";
5696       attr_array[1] = NULL;
5697       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
5698                                &group_base, &group_count, 
5699                                LDAP_SCOPE_SUBTREE)) != 0)
5700         {
5701           com_err(whoami, 0, "Unable to process user %s : %s",
5702                   user_name, ldap_err2string(rc));
5703           return(rc);
5704         }
5705     }
5706   
5707   if (group_count != 1)
5708     {
5709       linklist_free(group_base);
5710       com_err(whoami, 0, "Unable to find user %s in directory",
5711               user_name);
5712       return(LDAP_NO_SUCH_OBJECT);
5713     }
5714
5715   strcpy(distinguished_name, group_base->dn);
5716   ulongValue = atoi((*group_base).value);
5717
5718   if (operation == MEMBER_DEACTIVATE)
5719     ulongValue |= UF_ACCOUNTDISABLE;
5720   else    
5721     ulongValue &= ~UF_ACCOUNTDISABLE;
5722
5723   sprintf(temp, "%ld", ulongValue);
5724
5725   if ((rc = construct_newvalues(group_base, group_count, (*group_base).value, 
5726                                 temp, &modvalues, REPLACE)) == 1)
5727     goto cleanup;
5728
5729   linklist_free(group_base);
5730   group_base = NULL;
5731   group_count = 0;
5732   n = 0;
5733   ADD_ATTR("UserAccountControl", modvalues, LDAP_MOD_REPLACE);
5734
5735   if (strlen(MoiraId) != 0)
5736     {
5737     mitMoiraId_v[0] = MoiraId;
5738     ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
5739     }
5740
5741   mods[n] = NULL;
5742   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
5743
5744   for (i = 0; i < n; i++)
5745     free(mods[i]);
5746
5747   free_values(modvalues);
5748
5749   if (rc != LDAP_SUCCESS)
5750     {
5751       com_err(whoami, 0, "Unable to change status of user %s : %s",
5752               user_name, ldap_err2string(rc));
5753     }
5754   
5755  cleanup:
5756   return(rc);
5757 }
5758
5759 int user_delete(LDAP *ldap_handle, char *dn_path, 
5760                 char *u_name, char *MoiraId)
5761 {
5762   char      filter[128];
5763   char      *attr_array[3];
5764   char      distinguished_name[1024];
5765   char      user_name[512];
5766   LK_ENTRY  *group_base;
5767   int       group_count;
5768   int       rc;
5769   char      temp[256];
5770
5771   if (!check_string(u_name))
5772     return(AD_INVALID_NAME);
5773
5774   strcpy(user_name, u_name);
5775   group_count = 0;
5776   group_base = NULL;
5777
5778   if (strlen(MoiraId) != 0)
5779     {
5780       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
5781       attr_array[0] = "name";
5782       attr_array[1] = NULL;
5783       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
5784                                &group_base, &group_count, 
5785                                LDAP_SCOPE_SUBTREE)) != 0)
5786         {
5787           com_err(whoami, 0, "Unable to process user %s : %s",
5788                   user_name, ldap_err2string(rc));
5789           goto cleanup;
5790         }
5791     }
5792   
5793   if (group_count != 1)
5794     {
5795       linklist_free(group_base);
5796       group_count = 0;
5797       group_base = NULL;
5798       sprintf(filter, "(sAMAccountName=%s)", user_name);
5799       attr_array[0] = "name";
5800       attr_array[1] = NULL;
5801       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
5802                                &group_base, &group_count, 
5803                                LDAP_SCOPE_SUBTREE)) != 0)
5804         {
5805           com_err(whoami, 0, "Unable to process user %s : %s",
5806                   user_name, ldap_err2string(rc));
5807           goto cleanup;
5808         }
5809     }
5810
5811   if (group_count != 1)
5812     {
5813       goto cleanup;
5814     }
5815   
5816   strcpy(distinguished_name, group_base->dn);
5817
5818   if (rc = ldap_delete_s(ldap_handle, distinguished_name))
5819     {
5820       com_err(whoami, 0, "Unable to process user %s : %s",
5821               user_name, ldap_err2string(rc));
5822     }
5823
5824   /* Need to add code to delete mit.edu contact */
5825   
5826   if (Exchange)
5827     {
5828       sprintf(temp, "cn=%s@mit.edu,%s,%s", user_name, contact_ou, dn_path);
5829
5830       if(rc = ldap_delete_s(ldap_handle, temp))
5831         {
5832           com_err(whoami, 0, "Unable to delete user contact for %s",
5833                   user_name);
5834         }
5835     }
5836
5837  cleanup:
5838   linklist_free(group_base);
5839
5840   return(0);
5841 }
5842
5843 void linklist_free(LK_ENTRY *linklist_base)
5844 {
5845   LK_ENTRY *linklist_previous;
5846
5847   while (linklist_base != NULL)
5848     {
5849       if (linklist_base->dn != NULL)
5850         free(linklist_base->dn);
5851
5852       if (linklist_base->attribute != NULL)
5853         free(linklist_base->attribute);
5854
5855       if (linklist_base->value != NULL)
5856         free(linklist_base->value);
5857
5858       if (linklist_base->member != NULL)
5859         free(linklist_base->member);
5860
5861       if (linklist_base->type != NULL)
5862         free(linklist_base->type);
5863
5864       if (linklist_base->list != NULL)
5865         free(linklist_base->list);
5866
5867       linklist_previous = linklist_base;
5868       linklist_base = linklist_previous->next;
5869       free(linklist_previous);
5870     }
5871 }
5872
5873 void free_values(char **modvalues)
5874 {
5875   int i;
5876
5877   i = 0;
5878
5879   if (modvalues != NULL)
5880     {
5881     while (modvalues[i] != NULL)
5882       {
5883         free(modvalues[i]);
5884         modvalues[i] = NULL;
5885         ++i;
5886       }
5887     free(modvalues);
5888   }
5889 }
5890
5891 static int illegalchars[] = {
5892   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
5893   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
5894   1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, /* SPACE - / */
5895   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 0 - ? */
5896   0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
5897   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* P - _ */
5898   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
5899   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
5900   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5901   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5902   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5903   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5904   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5905   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5906   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5907   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5908 };
5909
5910 static int illegalchars_ldap[] = {
5911   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
5912   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
5913   0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, /* SPACE - / */
5914   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, /* 0 - ? */
5915   0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
5916   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, /* P - _ */
5917   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
5918   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
5919   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5920   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5921   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5922   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5923   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5924   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5925   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5926   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5927 };
5928
5929 int check_string(char *s)
5930 {
5931   char  character;
5932   char  *string;
5933
5934   string = s;
5935
5936   for (; *s; s++)
5937     {
5938       character = *s;
5939
5940       if (isupper(character))
5941         character = tolower(character);
5942
5943       if(ActiveDirectory)
5944         {
5945           if (illegalchars[(unsigned) character])
5946             {
5947               com_err(whoami, 0, "Found illegal char '%c' (%d) in string %s",
5948                       character, (unsigned) character, string);
5949               return 0;
5950             }
5951         }
5952       else
5953         {
5954           if (illegalchars_ldap[(unsigned) character])
5955             {
5956               com_err(whoami, 0, "Found illegal char '%c' (%d) in string %s",
5957                       character, (unsigned) character, string);
5958               return 0;
5959             }
5960         }
5961     }
5962
5963   return(1);
5964 }
5965
5966 int check_container_name(char *s)
5967 {
5968   char  character;
5969
5970   for (; *s; s++)
5971     {
5972       character = *s;
5973
5974       if (isupper(character))
5975         character = tolower(character);
5976
5977       if (character == ' ')
5978         continue;
5979
5980       if (illegalchars[(unsigned) character])
5981         return 0;
5982     }
5983
5984   return(1);
5985 }
5986
5987 int mr_connect_cl(char *server, char *client, int version, int auth)
5988 {
5989   int   status;
5990   char  *motd;
5991   char  temp[128];
5992
5993   status = mr_connect(server);
5994
5995   if (status)
5996     {
5997       com_err(whoami, status, "while connecting to Moira");
5998       return status;
5999     }
6000
6001   status = mr_motd(&motd);
6002
6003   if (status)
6004     {
6005       mr_disconnect();
6006       com_err(whoami, status, "while checking server status");
6007       return status;
6008     }
6009
6010   if (motd)
6011     {
6012       sprintf(temp, "The Moira server is currently unavailable: %s", motd);
6013       com_err(whoami, status, temp);
6014       mr_disconnect();
6015       return status;
6016     }
6017
6018   status = mr_version(version);
6019
6020   if (status)
6021     {
6022       if (status == MR_UNKNOWN_PROC)
6023         {
6024           if (version > 2)
6025             status = MR_VERSION_HIGH;
6026           else
6027             status = MR_SUCCESS;
6028         }
6029
6030       if (status == MR_VERSION_HIGH)
6031         {
6032           com_err(whoami, 0, "Warning: This client is running newer code "
6033                   "than the server.");
6034                   com_err(whoami, 0, "Some operations may not work.");
6035         }
6036       else if (status && status != MR_VERSION_LOW)
6037         {
6038           com_err(whoami, status, "while setting query version number.");
6039           mr_disconnect();
6040           return status;
6041         }
6042     }
6043
6044   if (auth)
6045     {
6046       status = mr_krb5_auth(client);
6047       if (status)
6048         {
6049           com_err(whoami, status, "while authenticating to Moira.");
6050           mr_disconnect();
6051           return status;
6052         }
6053     }
6054   
6055   return MR_SUCCESS;
6056 }
6057
6058 void AfsToWinAfs(char* path, char* winPath)
6059 {
6060   char* pathPtr;
6061   char* winPathPtr;
6062   strcpy(winPath, WINAFS);
6063   pathPtr = path + strlen(AFS);
6064   winPathPtr = winPath + strlen(WINAFS);
6065   
6066   while (*pathPtr)
6067     {
6068       if (*pathPtr == '/')
6069         *winPathPtr = '\\';
6070       else
6071         *winPathPtr = *pathPtr;
6072       
6073       pathPtr++;
6074       winPathPtr++;
6075     }
6076 }
6077
6078 int GetAceInfo(int ac, char **av, void *ptr)
6079 {
6080   char **call_args;
6081   int   security_flag;
6082
6083   call_args = ptr;
6084   
6085   strcpy(call_args[0], av[L_ACE_TYPE]);
6086   strcpy(call_args[1], av[L_ACE_NAME]);
6087   security_flag = 0;
6088   get_group_membership(call_args[2], call_args[3], &security_flag, av);
6089   return(LDAP_SUCCESS);  
6090 }
6091
6092 int checkADname(LDAP *ldap_handle, char *dn_path, char *Name)
6093 {
6094   char filter[128];
6095   char *attr_array[3];
6096   int  group_count;
6097   int  rc;
6098   LK_ENTRY  *group_base;
6099   
6100   group_count = 0;
6101   group_base = NULL;
6102   
6103   sprintf(filter, "(sAMAccountName=%s)", Name);
6104   attr_array[0] = "sAMAccountName";
6105   attr_array[1] = NULL;
6106
6107   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6108                            &group_base, &group_count, 
6109                            LDAP_SCOPE_SUBTREE)) != 0)
6110     {
6111       com_err(whoami, 0, "Unable to process ACE name %s : %s",
6112               Name, ldap_err2string(rc));
6113       return(1);
6114     }
6115
6116   linklist_free(group_base);
6117   group_base = NULL;
6118
6119   if (group_count == 0)
6120     return(0);
6121   
6122   return(1);
6123 }
6124
6125 #define MAX_ACE 7
6126
6127 int ProcessAce(LDAP *ldap_handle, char *dn_path, char *Name, char *Type, 
6128                int UpdateGroup, int *ProcessGroup, char *maillist,
6129                char *nfsgroup)
6130 {
6131   char  *av[2];
6132   char  GroupName[256];
6133   char  *call_args[7];
6134   int   rc;
6135   char  *AceInfo[4];
6136   char  AceType[32];
6137   char  AceName[128];
6138   char  AceMembership[2];
6139   char  AceOu[256];
6140   char  temp[128];
6141   char  *save_argv[U_END];
6142
6143   if (!SetGroupAce)
6144     {
6145       com_err(whoami, 0, "ProcessAce disabled, skipping");
6146       return(0);
6147     }
6148
6149   strcpy(GroupName, Name);
6150   
6151   if (strcasecmp(Type, "LIST"))
6152     return(1);
6153
6154   while (1)
6155     {
6156       av[0] = GroupName;
6157       AceInfo[0] = AceType;
6158       AceInfo[1] = AceName;
6159       AceInfo[2] = AceMembership;
6160       AceInfo[3] = AceOu;
6161       memset(AceType, '\0', sizeof(AceType));
6162       memset(AceName, '\0', sizeof(AceName));
6163       memset(AceMembership, '\0', sizeof(AceMembership));
6164       memset(AceOu, '\0', sizeof(AceOu));
6165       callback_rc = 0;
6166     
6167       if (rc = mr_query("get_list_info", 1, av, GetAceInfo, AceInfo))
6168         { 
6169           if(rc != MR_NO_MATCH)
6170             com_err(whoami, 0, "Unable to get ACE info for list %s : %s", 
6171                     GroupName, error_message(rc));
6172
6173           return(1);
6174         }
6175
6176       if (callback_rc)
6177         {
6178           com_err(whoami, 0, "Unable to get ACE info for list %s", GroupName);
6179           return(1);
6180         }
6181
6182       if ((strcasecmp(AceType, "USER")) && (strcasecmp(AceType, "LIST")))
6183         return(0);
6184
6185       strcpy(temp, AceName);
6186
6187       if (!strcasecmp(AceType, "LIST"))
6188         sprintf(temp, "%s%s", AceName, group_suffix);
6189
6190       if (!UpdateGroup)
6191         {
6192           if (checkADname(ldap_handle, dn_path, temp))
6193               return(0);
6194
6195           (*ProcessGroup) = 1;
6196         }
6197
6198       if (!strcasecmp(AceInfo[0], "LIST"))
6199         {
6200           if (make_new_group(ldap_handle, dn_path, "", AceName, AceOu, 
6201                              AceMembership, 0, UpdateGroup, maillist,
6202                              nfsgroup))
6203             return(1);
6204
6205           populate_group(ldap_handle, dn_path, AceName, AceOu, AceMembership,
6206                          0, "", 1);
6207         }
6208       else if (!strcasecmp(AceInfo[0], "USER"))
6209         {
6210           av[0] = AceName;
6211           call_args[0] = (char *)ldap_handle;
6212           call_args[1] = dn_path;
6213           call_args[2] = "";
6214           call_args[3] = NULL;
6215           callback_rc = 0;
6216
6217           if(!strcasecmp(AceName, PRODUCTION_PRINCIPAL) ||
6218              !strcasecmp(AceName, TEST_PRINCIPAL))
6219             {
6220               return(1);
6221             }
6222
6223           if (rc = mr_query("get_user_account_by_login", 1, av, 
6224                             save_query_info, save_argv))
6225             {
6226               com_err(whoami, 0, "Unable to process user ACE %s for group %s.",
6227                       AceName, Name);
6228               return(1);
6229             }
6230
6231           if (rc = user_create(U_END, save_argv, call_args)) 
6232             {
6233               com_err(whoami, 0, "Unable to process user ACE %s for group %s.",
6234                       AceName, Name);
6235               return(1);
6236             }
6237           
6238           if (callback_rc)
6239             {
6240               com_err(whoami, 0, "Unable to process user Ace %s for group %s",
6241                       AceName, Name);
6242               return(1);
6243             }
6244
6245           return(0);
6246         }
6247       else
6248         return(1);
6249
6250       if (!strcasecmp(AceType, "LIST"))
6251         {
6252           if (!strcasecmp(GroupName, AceName))
6253             return(0);
6254         }
6255
6256       strcpy(GroupName, AceName);
6257     }
6258   
6259   return(1);
6260 }
6261
6262 int make_new_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
6263                    char *group_name, char *group_ou, char *group_membership, 
6264                    int group_security_flag, int updateGroup, char *maillist,
6265                    char *nfsgroup)
6266 {
6267   char  *av[3];
6268   char  *call_args[8];
6269   int   rc;
6270   LK_ENTRY  *group_base;
6271   int  group_count;
6272   char filter[128];
6273   char *attr_array[3];
6274
6275   av[0] = group_name;
6276   call_args[0] = (char *)ldap_handle;
6277   call_args[1] = dn_path;
6278   call_args[2] = group_name;
6279   call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
6280   call_args[4] = (char *)updateGroup;
6281   call_args[5] = MoiraId;
6282   call_args[6] = "0";
6283   call_args[7] = NULL;
6284   callback_rc = 0;
6285
6286   group_count = 0;
6287   group_base = NULL;
6288
6289   if (rc = mr_query("get_list_info", 1, av, group_create, call_args))
6290     {
6291       moira_disconnect();
6292       com_err(whoami, 0, "Unable to create list %s : %s", group_name, 
6293               error_message(rc));
6294       return(rc);
6295     }
6296
6297   if (callback_rc)
6298     {
6299       moira_disconnect();
6300       com_err(whoami, 0, "Unable to create list %s", group_name);
6301       return(callback_rc);
6302     }
6303
6304   return(0);
6305 }
6306
6307 int populate_group(LDAP *ldap_handle, char *dn_path, char *group_name, 
6308                    char *group_ou, char *group_membership, 
6309                    int group_security_flag, char *MoiraId, 
6310                    int synchronize)
6311 {
6312   char      *av[3];
6313   char      *call_args[7];
6314   char      *pUserOu;
6315   LK_ENTRY  *ptr;
6316   int       rc;
6317   char      member[512];
6318   char      *s;
6319   char      **members;
6320   int       i = 0;
6321   int       j = 0;
6322   int       n = 0;
6323   char      group_dn[512];
6324   LDAPMod   *mods[20];
6325   char      *member_v[] = {NULL, NULL};
6326   char      *save_argv[U_END];
6327   char      machine_ou[256];
6328   char      NewMachineName[1024];
6329
6330   com_err(whoami, 0, "Populating group %s", group_name);
6331   av[0] = group_name;
6332   call_args[0] = (char *)ldap_handle;
6333   call_args[1] = dn_path;
6334   call_args[2] = group_name;
6335   call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS | 
6336                           MOIRA_MACHINE);
6337   call_args[4] = NULL;
6338   member_base = NULL;
6339   group_members = 0;
6340
6341   if (rc = mr_query("get_end_members_of_list", 1, av,
6342                     member_list_build, call_args))
6343     {
6344       if(rc == MR_LIST)
6345         return(0);
6346       
6347       com_err(whoami, 0, "Unable to populate list %s : %s", 
6348               group_name, error_message(rc));
6349       return(3);
6350     }
6351
6352   if (member_base != NULL)
6353     {
6354       ptr = member_base;
6355
6356       while(ptr != NULL)
6357         {
6358           if (!strcasecmp(ptr->type, "LIST"))
6359             {
6360               ptr = ptr->next;
6361               continue;
6362             }
6363
6364           if (!strcasecmp(ptr->type, "MACHINE") && !ProcessMachineContainer)
6365             {
6366               ptr = ptr->next;
6367               continue;
6368             }
6369
6370           if(!strcasecmp(ptr->type, "USER"))
6371             {
6372               if(!strcasecmp(ptr->member, PRODUCTION_PRINCIPAL) ||
6373                  !strcasecmp(ptr->member, TEST_PRINCIPAL))
6374                 {
6375                   ptr = ptr->next;
6376                   continue;
6377                 }
6378             }
6379
6380           ptr = ptr->next;
6381           group_members++;
6382         }
6383     }
6384
6385   if(max_group_members && !synchronize && (group_members > max_group_members))
6386     {
6387       com_err(whoami, 0, 
6388               "Group %s membership of %d exceeds maximum %d, skipping",
6389               group_name, group_members, max_group_members);
6390       return(0);
6391     }
6392
6393   members = (char **)malloc(sizeof(char *) * 2);
6394
6395   if (member_base != NULL)
6396     {
6397       ptr = member_base;
6398
6399       while (ptr != NULL)
6400         {
6401           if (!strcasecmp(ptr->type, "LIST"))
6402             {
6403               ptr = ptr->next;
6404               continue;
6405             }
6406           
6407           if (!strcasecmp(ptr->type, "MACHINE") && !ProcessMachineContainer)
6408             {
6409               ptr = ptr->next;
6410               continue;
6411             }
6412             
6413           if(!strcasecmp(ptr->type, "USER"))
6414             {
6415               if(!strcasecmp(ptr->member, PRODUCTION_PRINCIPAL) ||
6416                  !strcasecmp(ptr->member, TEST_PRINCIPAL))
6417                 {
6418                   ptr = ptr->next;
6419                   continue;
6420                 }
6421
6422               if ((rc = check_user(ldap_handle, dn_path, ptr->member,
6423                                    "")) == AD_NO_USER_FOUND)
6424                 {
6425                   com_err(whoami, 0, "creating user %s", ptr->member);
6426
6427                   av[0] = ptr->member;
6428                   call_args[0] = (char *)ldap_handle;
6429                   call_args[1] = dn_path;
6430                   call_args[2] = "";
6431                   call_args[3] = NULL;
6432                   callback_rc = 0;
6433                   
6434                   if (rc = mr_query("get_user_account_by_login", 1, av, 
6435                                     save_query_info, save_argv))
6436                     {
6437                       com_err(whoami, 0, "Unable to create user %s " 
6438                               "while populating group %s.", ptr->member,
6439                               group_name);
6440
6441                       return(3);
6442                     }
6443
6444                   if (rc = user_create(U_END, save_argv, call_args)) 
6445                     {
6446                       com_err(whoami, 0, "Unable to create user %s "
6447                               "while populating group %s.", ptr->member,
6448                               group_name);
6449                       
6450                       return(3);
6451                     }
6452           
6453                   if (callback_rc)
6454                     {
6455                       com_err(whoami, 0, "Unable to create user %s "
6456                               "while populating group %s", ptr->member, 
6457                               group_name);
6458
6459                       return(3);
6460                     }
6461                 }
6462
6463               pUserOu = user_ou;
6464                   
6465               if(ActiveDirectory) 
6466                 {
6467                   sprintf(member, "cn=%s,%s,%s", ptr->member, pUserOu, 
6468                           dn_path);
6469                 }
6470               else 
6471                 {
6472                   sprintf(member, "uid=%s,%s,%s", ptr->member, pUserOu, 
6473                           dn_path);
6474                 }
6475             }
6476           else if (!strcasecmp(ptr->type, "STRING"))
6477             {
6478               if (contact_create(ldap_handle, dn_path, ptr->member,
6479                                  contact_ou))
6480                 return(3);
6481
6482               pUserOu = contact_ou;
6483               sprintf(member, "cn=%s,%s,%s", escape_string(ptr->member), 
6484                       pUserOu, dn_path);
6485             }
6486           else if (!strcasecmp(ptr->type, "KERBEROS"))
6487             {
6488               if (contact_create(ldap_handle, dn_path, ptr->member, 
6489                                  kerberos_ou))
6490                 return(3);
6491
6492               pUserOu = kerberos_ou;
6493               sprintf(member, "cn=%s,%s,%s", escape_string(ptr->member), 
6494                       pUserOu, dn_path);
6495             }
6496           else if (!strcasecmp(ptr->type, "MACHINE"))
6497             {
6498               memset(machine_ou, '\0', sizeof(machine_ou));
6499               memset(NewMachineName, '\0', sizeof(NewMachineName));
6500
6501               if (!get_machine_ou(ldap_handle, dn_path, ptr->member,
6502                                  machine_ou, NewMachineName))
6503                 {
6504                   pUserOu = machine_ou;
6505                   sprintf(member, "cn=%s,%s,%s", NewMachineName, pUserOu,
6506                           dn_path);
6507                 }
6508               else
6509                 {
6510                   ptr = ptr->next;                  
6511                   continue;
6512                 }
6513             }
6514
6515           if(i > 1) 
6516             members = (char **)realloc(members, ((i + 2) * sizeof(char *)));
6517           members[i++] = strdup(member);
6518
6519           ptr = ptr->next;
6520         }
6521     
6522       linklist_free(member_base);
6523       member_base = NULL;
6524     }
6525
6526   members[i] = NULL;
6527
6528   sprintf(group_dn, "cn=%s,%s,%s", group_name, group_ou, dn_path);
6529
6530   if(GroupPopulateDelete)
6531     {
6532       n = 0;
6533       ADD_ATTR("member", member_v, LDAP_MOD_REPLACE);
6534       mods[n] = NULL;
6535       
6536       if ((rc = ldap_modify_s(ldap_handle, group_dn, 
6537                               mods)) != LDAP_SUCCESS)
6538         {
6539           com_err(whoami, 0,
6540                   "Unable to populate group membership for %s: %s",
6541                   group_dn, ldap_err2string(rc));
6542         }
6543   
6544       for (i = 0; i < n; i++)
6545         free(mods[i]);
6546     }
6547
6548   n = 0;
6549   ADD_ATTR("member", members, LDAP_MOD_REPLACE);
6550   mods[n] = NULL;
6551
6552   if ((rc = ldap_modify_s(ldap_handle, group_dn, 
6553                           mods)) != LDAP_SUCCESS)
6554     {
6555       com_err(whoami, 0,
6556               "Unable to populate group membership for %s: %s",
6557               group_dn, ldap_err2string(rc));
6558     }
6559   
6560   for (i = 0; i < n; i++)
6561     free(mods[i]);
6562     
6563   free(members);
6564
6565   return(0);
6566 }
6567
6568 int process_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
6569                   char *group_name, char *group_ou, char *group_membership, 
6570                   int group_security_flag, int type, char *maillist, 
6571                   char *nfsgroup)
6572 {
6573   char      before_desc[512];
6574   char      before_name[256];
6575   char      before_group_ou[256];
6576   char      before_group_membership[2];
6577   char      distinguishedName[256];
6578   char      ad_distinguishedName[256];
6579   char      filter[128];
6580   char      *attr_array[3];
6581   int       before_security_flag;
6582   int       group_count;
6583   int       rc;
6584   LK_ENTRY  *group_base;
6585   LK_ENTRY  *ptr;
6586   char      ou_both[512];
6587   char      ou_security[512];
6588   char      ou_distribution[512];
6589   char      ou_neither[512];
6590   char      group_dn[512];
6591
6592   memset(ad_distinguishedName, '\0', sizeof(ad_distinguishedName));
6593   sprintf(distinguishedName, "CN=%s,%s,%s", group_name, group_ou, dn_path);
6594
6595   memset(filter, '\0', sizeof(filter));
6596   group_base = NULL;
6597   group_count = 0;
6598
6599   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
6600                         "*", MoiraId, 
6601                         "samAccountName", &group_base, 
6602                         &group_count, filter))
6603     return(rc);
6604
6605   if (type == CHECK_GROUPS)
6606     {
6607       if (group_count == 1)
6608         {
6609           strcpy(group_dn, group_base->dn);
6610
6611           if (!strcasecmp(group_dn, distinguishedName))
6612             {
6613               linklist_free(group_base);
6614               return(0);
6615             }
6616         }
6617
6618       linklist_free(group_base);
6619
6620       if (group_count == 0)
6621         return(AD_NO_GROUPS_FOUND);
6622
6623       if (group_count == 1)
6624         return(AD_WRONG_GROUP_DN_FOUND);
6625
6626       return(AD_MULTIPLE_GROUPS_FOUND);
6627     }
6628
6629   if (group_count == 0)
6630     {
6631       return(AD_NO_GROUPS_FOUND);
6632     }
6633
6634   if (group_count > 1)
6635     {
6636       ptr = group_base;
6637
6638       strcpy(group_dn, ptr->dn);
6639
6640       while (ptr != NULL)
6641         {
6642           if (!strcasecmp(group_dn, ptr->value))
6643             break;
6644
6645           ptr = ptr->next;
6646         }
6647
6648       if (ptr == NULL)
6649         {
6650           com_err(whoami, 0, "%d groups with moira id = %s", group_count, 
6651                   MoiraId);
6652           ptr = group_base;
6653
6654           while (ptr != NULL)
6655             {
6656               com_err(whoami, 0, "%s with moira id = %s", ptr->value, MoiraId);
6657               ptr = ptr->next;
6658             }
6659
6660           linklist_free(group_base);
6661           return(AD_MULTIPLE_GROUPS_FOUND);
6662         }
6663
6664       ptr = group_base;
6665
6666       while (ptr != NULL)
6667         {
6668           strcpy(group_dn, ptr->dn);
6669
6670           if (strcasecmp(group_dn, ptr->value))
6671             rc = ldap_delete_s(ldap_handle, ptr->value);
6672
6673           ptr = ptr->next;
6674         }
6675
6676       linklist_free(group_base);
6677       memset(filter, '\0', sizeof(filter));
6678       group_base = NULL;
6679       group_count = 0;
6680
6681       if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
6682                             "*", MoiraId, 
6683                             "samAccountName", &group_base, 
6684                             &group_count, filter))
6685         return(rc);
6686
6687       if (group_count == 0)
6688         return(AD_NO_GROUPS_FOUND);
6689
6690       if (group_count > 1)
6691         return(AD_MULTIPLE_GROUPS_FOUND);
6692     }
6693
6694   strcpy(ad_distinguishedName, group_base->dn);
6695   linklist_free(group_base);
6696   group_base = NULL;
6697   group_count = 0;
6698
6699   attr_array[0] = "sAMAccountName";
6700   attr_array[1] = NULL;
6701   
6702   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6703                            &group_base, &group_count, 
6704                            LDAP_SCOPE_SUBTREE)) != 0)
6705     {
6706       com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6707               MoiraId, ldap_err2string(rc));
6708       return(rc);
6709     }
6710   
6711   sprintf(filter, "(sAMAccountName=%s)", group_base->value);
6712
6713   if (!strcasecmp(ad_distinguishedName, distinguishedName))
6714     {
6715       linklist_free(group_base);
6716       group_base = NULL;
6717       group_count = 0;
6718       return(0);
6719     }
6720
6721   linklist_free(group_base);
6722   group_base = NULL;
6723   group_count = 0;
6724   memset(ou_both, '\0', sizeof(ou_both));
6725   memset(ou_security, '\0', sizeof(ou_security));
6726   memset(ou_distribution, '\0', sizeof(ou_distribution));
6727   memset(ou_neither, '\0', sizeof(ou_neither));
6728   memset(before_name, '\0', sizeof(before_name));
6729   memset(before_desc, '\0', sizeof(before_desc));
6730   memset(before_group_membership, '\0', sizeof(before_group_membership));
6731   
6732   attr_array[0] = "name";
6733   attr_array[1] = NULL;
6734
6735   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6736                            &group_base, &group_count, 
6737                            LDAP_SCOPE_SUBTREE)) != 0)
6738     {
6739       com_err(whoami, 0, "Unable to get list name with MoiraId = %s: %s",
6740               MoiraId, ldap_err2string(rc));
6741       return(rc);
6742     }
6743
6744   strcpy(before_name, group_base->value);
6745   linklist_free(group_base);
6746   group_base = NULL;
6747   group_count = 0;
6748
6749   attr_array[0] = "description";
6750   attr_array[1] = NULL;
6751   
6752   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6753                            &group_base, &group_count, 
6754                            LDAP_SCOPE_SUBTREE)) != 0)
6755     {
6756       com_err(whoami, 0, 
6757               "Unable to get list description with MoiraId = %s: %s",
6758               MoiraId, ldap_err2string(rc));
6759       return(rc);
6760     }
6761
6762   if (group_count != 0)
6763     {
6764       strcpy(before_desc, group_base->value);
6765       linklist_free(group_base);
6766       group_base = NULL;
6767       group_count = 0;
6768     }
6769  
6770   change_to_lower_case(ad_distinguishedName);  
6771   strcpy(ou_both, group_ou_both);
6772   change_to_lower_case(ou_both);
6773   strcpy(ou_security, group_ou_security);
6774   change_to_lower_case(ou_security);
6775   strcpy(ou_distribution, group_ou_distribution);
6776   change_to_lower_case(ou_distribution);
6777   strcpy(ou_neither, group_ou_neither);
6778   change_to_lower_case(ou_neither);
6779
6780   if (strstr(ad_distinguishedName, ou_both))
6781     {
6782       strcpy(before_group_ou, group_ou_both);
6783       before_group_membership[0] = 'B';
6784       before_security_flag = 1;
6785     }
6786   else if (strstr(ad_distinguishedName, ou_security))
6787     {
6788       strcpy(before_group_ou, group_ou_security);
6789       before_group_membership[0] = 'S';
6790       before_security_flag = 1;
6791     }
6792   else if (strstr(ad_distinguishedName, ou_distribution))
6793     {
6794       strcpy(before_group_ou, group_ou_distribution);
6795       before_group_membership[0] = 'D';
6796       before_security_flag = 0;
6797     }
6798   else if (strstr(ad_distinguishedName, ou_neither))
6799     {
6800       strcpy(before_group_ou, group_ou_neither);
6801       before_group_membership[0] = 'N';
6802       before_security_flag = 0;
6803     }
6804   else
6805     return(AD_NO_OU_FOUND);
6806
6807   rc = group_rename(ldap_handle, dn_path, before_name, 
6808                     before_group_membership, 
6809                     before_group_ou, before_security_flag, before_desc,
6810                     group_name, group_membership, group_ou, 
6811                     group_security_flag,
6812                     before_desc, MoiraId, filter, maillist, nfsgroup);
6813
6814   return(rc);
6815 }
6816
6817 void change_to_lower_case(char *ptr)
6818 {
6819   int i;
6820
6821   for (i = 0; i < (int)strlen(ptr); i++)
6822     {
6823       ptr[i] = tolower(ptr[i]);
6824     }
6825 }
6826
6827 int ad_get_group(LDAP *ldap_handle, char *dn_path, 
6828                  char *group_name, char *group_membership, 
6829                  char *MoiraId, char *attribute,
6830                  LK_ENTRY **linklist_base, int *linklist_count,
6831                  char *rFilter)
6832 {
6833   LK_ENTRY  *pPtr;
6834   char  filter[128];
6835   char  *attr_array[3];
6836   char  *dn;
6837   int   rc;
6838
6839   (*linklist_base) = NULL;
6840   (*linklist_count) = 0;
6841
6842   if (strlen(rFilter) != 0)
6843     {
6844       strcpy(filter, rFilter);
6845       attr_array[0] = attribute;
6846       attr_array[1] = NULL;
6847       
6848       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6849                                linklist_base, linklist_count, 
6850                                LDAP_SCOPE_SUBTREE)) != 0)
6851         {
6852           com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6853                   MoiraId, ldap_err2string(rc));
6854          return(rc);
6855        }
6856
6857     if ((*linklist_count) == 1)
6858       {
6859         strcpy(rFilter, filter);
6860         return(0);
6861       }
6862     }
6863
6864   linklist_free((*linklist_base));
6865   (*linklist_base) = NULL;
6866   (*linklist_count) = 0;
6867
6868   if (strlen(MoiraId) != 0)
6869     {
6870       sprintf(filter, "(&(objectClass=group)(mitMoiraId=%s))", MoiraId);
6871
6872       attr_array[0] = attribute;
6873       attr_array[1] = NULL;
6874
6875       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6876                                linklist_base, linklist_count, 
6877                                LDAP_SCOPE_SUBTREE)) != 0)
6878         {
6879           com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6880                   MoiraId, ldap_err2string(rc));
6881          return(rc);
6882        }
6883     }
6884
6885   if ((*linklist_count) > 1)
6886     {
6887       com_err(whoami, 0, "multiple groups with mitMoiraId = %s", MoiraId);
6888       pPtr = (*linklist_base);
6889
6890       while (pPtr)
6891         {
6892           com_err(whoami, 0, "groups %s has mitMoiraId = %s", pPtr->value, 
6893                   MoiraId);
6894           pPtr = pPtr->next;
6895         }
6896
6897       linklist_free((*linklist_base));
6898       (*linklist_base) = NULL;
6899       (*linklist_count) = 0;
6900     }
6901
6902   if ((*linklist_count) == 1)
6903     {
6904
6905       pPtr = (*linklist_base);
6906       dn = strdup(pPtr->dn);
6907       dn += 3;
6908
6909       if (!memcmp(dn, group_name, strlen(group_name)))
6910         {
6911           strcpy(rFilter, filter);
6912           return(0);
6913         }
6914     }
6915
6916   linklist_free((*linklist_base));
6917   (*linklist_base) = NULL;
6918   (*linklist_count) = 0;
6919   sprintf(filter, "(sAMAccountName=%s%s)", group_name, group_suffix);
6920
6921   attr_array[0] = attribute;
6922   attr_array[1] = NULL;
6923
6924   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6925                            linklist_base, linklist_count, 
6926                            LDAP_SCOPE_SUBTREE)) != 0)
6927     {
6928       com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6929               MoiraId, ldap_err2string(rc));
6930       return(rc);
6931     }
6932
6933   if ((*linklist_count) == 1)
6934     {
6935       strcpy(rFilter, filter);
6936       return(0);
6937     }
6938
6939   return(0);
6940 }
6941
6942 int check_user(LDAP *ldap_handle, char *dn_path, char *UserName, char *MoiraId)
6943 {
6944   char filter[128];
6945   char *attr_array[3];
6946   char SamAccountName[64];
6947   int  group_count;
6948   int  rc;
6949   LK_ENTRY  *group_base;
6950   LK_ENTRY  *gPtr;
6951
6952   group_count = 0;
6953   group_base = NULL;
6954
6955   if (strlen(MoiraId) != 0)
6956     {
6957       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
6958
6959       attr_array[0] = "sAMAccountName";
6960       attr_array[1] = NULL;
6961       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6962                                &group_base, &group_count, 
6963                                LDAP_SCOPE_SUBTREE)) != 0)
6964         {
6965           com_err(whoami, 0, "Unable to process user %s : %s",
6966                   UserName, ldap_err2string(rc));
6967           return(rc);
6968         }
6969
6970       if (group_count > 1)
6971         {
6972           com_err(whoami, 0, "multiple users exist with MoiraId = %s",
6973                   MoiraId);
6974           gPtr = group_base;
6975
6976           while (gPtr)
6977             {
6978               com_err(whoami, 0, "user %s exist with MoiraId = %s",
6979                       gPtr->value, MoiraId);
6980               gPtr = gPtr->next;
6981             }
6982         }
6983     }
6984
6985   if (group_count != 1)
6986     {
6987       linklist_free(group_base);
6988       group_count = 0;
6989       group_base = NULL;
6990       sprintf(filter, "(sAMAccountName=%s)", UserName);
6991       attr_array[0] = "sAMAccountName";
6992       attr_array[1] = NULL;
6993
6994       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6995                                &group_base, &group_count, 
6996                                LDAP_SCOPE_SUBTREE)) != 0)
6997         {
6998           com_err(whoami, 0, "Unable to process user %s : %s",
6999                   UserName, ldap_err2string(rc));
7000           return(rc);
7001         }
7002     }
7003
7004   if (group_count != 1)
7005     {
7006       linklist_free(group_base);
7007       return(AD_NO_USER_FOUND);
7008     }
7009
7010   strcpy(SamAccountName, group_base->value);
7011   linklist_free(group_base);
7012   group_count = 0;
7013   rc = 0;
7014
7015   if (strcmp(SamAccountName, UserName))
7016     {
7017       com_err(whoami, 0, 
7018               "User object %s with MoiraId %s has mismatched usernames " 
7019               "(LDAP username %s, Moira username %s)", SamAccountName,
7020               MoiraId, SamAccountName, UserName);
7021     }
7022
7023   return(0);
7024 }
7025
7026 void container_get_dn(char *src, char *dest)
7027 {
7028   char *sPtr;
7029   char *array[20];
7030   char name[256];
7031   int  n;
7032
7033   memset(array, '\0', 20 * sizeof(array[0]));
7034
7035   if (strlen(src) == 0)
7036     return;
7037
7038   strcpy(name, src);
7039   sPtr = name;
7040   n = 0;
7041   array[n] = name;
7042   ++n;
7043
7044   while (*sPtr)
7045     {
7046       if ((*sPtr) == '/')
7047         {
7048           (*sPtr) = '\0';
7049           ++sPtr;
7050           array[n] = sPtr;
7051           ++n;
7052         }
7053       else
7054         ++sPtr;
7055     }
7056
7057   strcpy(dest, "OU=");
7058
7059   while (n != 0)
7060     {
7061       strcat(dest, array[n-1]);
7062       --n;
7063       if (n > 0)
7064         {
7065           strcat(dest, ",OU=");
7066         }
7067     }
7068
7069   return;
7070 }
7071
7072 void container_get_name(char *src, char *dest)
7073 {
7074   char *sPtr;
7075   char *dPtr;
7076
7077   if (strlen(src) == 0)
7078     return;
7079
7080   sPtr = src;
7081   dPtr = src;
7082
7083   while (*sPtr)
7084     {
7085       if ((*sPtr) == '/')
7086         {
7087           dPtr = sPtr;
7088           ++dPtr;
7089         }
7090       ++sPtr;
7091     }
7092
7093   strcpy(dest, dPtr);
7094   return;
7095 }
7096
7097 void container_check(LDAP *ldap_handle, char *dn_path, char *name)
7098 {
7099   char cName[256];
7100   char *av[7];
7101   int  i;
7102   int  rc;
7103
7104   strcpy(cName, name);
7105
7106   for (i = 0; i < (int)strlen(cName); i++)
7107     {
7108       if (cName[i] == '/')
7109         {
7110           cName[i] = '\0';
7111           av[CONTAINER_NAME] = cName;
7112           av[CONTAINER_DESC] = "";
7113           av[CONTAINER_LOCATION] = "";
7114           av[CONTAINER_CONTACT] = "";
7115           av[CONTAINER_TYPE] = "";
7116           av[CONTAINER_ID] = "";
7117           av[CONTAINER_ROWID] = "";
7118           rc = container_create(ldap_handle, dn_path, 7, av);
7119
7120           if (rc == LDAP_SUCCESS)
7121             {
7122               com_err(whoami, 0, "container %s created without a mitMoiraId", 
7123                       cName);
7124             }
7125
7126           cName[i] = '/';
7127         }
7128     }
7129 }
7130
7131 int container_rename(LDAP *ldap_handle, char *dn_path, int beforec, 
7132                      char **before, int afterc, char **after)
7133 {
7134   char      dName[256];
7135   char      cName[256];
7136   char      new_cn[128];
7137   char      new_dn_path[256];
7138   char      temp[256];
7139   char      distinguishedName[256];
7140   char      *pPtr;
7141   int       rc;
7142   int       i;
7143
7144   memset(cName, '\0', sizeof(cName));
7145   container_get_name(after[CONTAINER_NAME], cName);
7146
7147   if (!check_container_name(cName))
7148     {
7149       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", 
7150               cName);
7151       return(AD_INVALID_NAME);
7152     }
7153
7154   memset(distinguishedName, '\0', sizeof(distinguishedName));
7155
7156   if (rc = container_get_distinguishedName(ldap_handle, dn_path, 
7157                                            distinguishedName, beforec, before))
7158     return(rc);
7159
7160   if (strlen(distinguishedName) == 0)
7161     {
7162       rc = container_create(ldap_handle, dn_path, afterc, after);
7163       return(rc);
7164     }
7165
7166   strcpy(temp, after[CONTAINER_NAME]);
7167   pPtr = temp;
7168
7169   for (i = 0; i < (int)strlen(temp); i++)
7170     {
7171       if (temp[i] == '/')
7172         {
7173           pPtr = &temp[i];
7174         }
7175     }
7176
7177   (*pPtr) = '\0';
7178
7179   container_get_dn(temp, dName);
7180
7181   if (strlen(temp) != 0)
7182     sprintf(new_dn_path, "%s,%s", dName, dn_path);
7183   else
7184     sprintf(new_dn_path, "%s", dn_path);
7185
7186   sprintf(new_cn, "OU=%s", cName);
7187
7188   container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
7189
7190   if ((rc = ldap_rename_s(ldap_handle, distinguishedName, new_cn, new_dn_path,
7191                           TRUE, NULL, NULL)) != LDAP_SUCCESS)
7192     {
7193       com_err(whoami, 0, "Unable to rename container from %s to %s : %s",
7194               before[CONTAINER_NAME], after[CONTAINER_NAME], 
7195               ldap_err2string(rc));
7196       return(rc);
7197     }
7198
7199   memset(dName, '\0', sizeof(dName));
7200   container_get_dn(after[CONTAINER_NAME], dName);
7201   rc = container_adupdate(ldap_handle, dn_path, dName, "", afterc, after);
7202
7203   return(rc);
7204 }
7205
7206 int container_delete(LDAP *ldap_handle, char *dn_path, int count, char **av)
7207 {
7208   char      distinguishedName[256];
7209   int       rc;
7210
7211   memset(distinguishedName, '\0', sizeof(distinguishedName));
7212
7213   if (rc = container_get_distinguishedName(ldap_handle, dn_path, 
7214                                            distinguishedName, count, av))
7215     return(rc);
7216
7217   if (strlen(distinguishedName) == 0)
7218     return(0);
7219
7220   if ((rc = ldap_delete_s(ldap_handle, distinguishedName)) != LDAP_SUCCESS)
7221     {
7222       if (rc == LDAP_NOT_ALLOWED_ON_NONLEAF)
7223         container_move_objects(ldap_handle, dn_path, distinguishedName);
7224       else
7225         com_err(whoami, 0, "Unable to delete container %s from directory : %s",
7226                 av[CONTAINER_NAME], ldap_err2string(rc));
7227     }
7228
7229   return(rc);
7230 }
7231
7232 int container_create(LDAP *ldap_handle, char *dn_path, int count, char **av)
7233 {
7234   char      *attr_array[3];
7235   LK_ENTRY  *group_base;
7236   int       group_count;
7237   LDAPMod   *mods[20];
7238   char      *objectClass_v[] = {"top", 
7239                            "organizationalUnit", 
7240                            NULL};
7241
7242   char *ou_v[] = {NULL, NULL};
7243   char *name_v[] = {NULL, NULL};
7244   char *moiraId_v[] = {NULL, NULL};
7245   char *desc_v[] = {NULL, NULL};
7246   char *managedBy_v[] = {NULL, NULL};
7247   char dName[256];
7248   char cName[256];
7249   char managedByDN[256];
7250   char filter[256];
7251   char temp[256];
7252   int  n;
7253   int  i;
7254   int  rc;
7255     
7256   memset(filter, '\0', sizeof(filter));
7257   memset(dName, '\0', sizeof(dName));
7258   memset(cName, '\0', sizeof(cName));
7259   memset(managedByDN, '\0', sizeof(managedByDN));
7260   container_get_dn(av[CONTAINER_NAME], dName);
7261   container_get_name(av[CONTAINER_NAME], cName);
7262
7263   if ((strlen(cName) == 0) || (strlen(dName) == 0))
7264     {
7265       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", 
7266               cName);
7267       return(AD_INVALID_NAME);
7268     }
7269
7270   if (!check_container_name(cName))
7271     {
7272       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", 
7273               cName);
7274       return(AD_INVALID_NAME);
7275     }
7276
7277   n = 0;
7278   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
7279   name_v[0] = cName;
7280   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
7281   ou_v[0] = cName;
7282   ADD_ATTR("ou", ou_v, LDAP_MOD_ADD);
7283
7284   if (strlen(av[CONTAINER_ROWID]) != 0)
7285     {
7286       moiraId_v[0] = av[CONTAINER_ROWID];
7287       ADD_ATTR("mitMoiraId", moiraId_v, LDAP_MOD_ADD);
7288     }
7289
7290   if (strlen(av[CONTAINER_DESC]) != 0)
7291     {
7292       desc_v[0] = av[CONTAINER_DESC];
7293       ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
7294     }
7295
7296   if ((strlen(av[CONTAINER_TYPE]) != 0) && (strlen(av[CONTAINER_ID]) != 0))
7297     {
7298       if (!strcasecmp(av[CONTAINER_TYPE], "KERBEROS"))
7299         {
7300           if (!contact_create(ldap_handle, dn_path, av[CONTAINER_ID], 
7301                               kerberos_ou))
7302             {
7303               sprintf(managedByDN, "CN=%s,%s,%s", av[CONTAINER_ID], 
7304                       kerberos_ou, dn_path);
7305               managedBy_v[0] = managedByDN;
7306               ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_ADD);
7307             }
7308         }
7309       else
7310         {
7311           if (!strcasecmp(av[CONTAINER_TYPE], "USER"))
7312             {
7313               sprintf(filter, "(&(cn=%s)(&(objectCategory=person)"
7314                       "(objectClass=user)))", av[CONTAINER_ID]);
7315             }
7316
7317           if (!strcasecmp(av[CONTAINER_TYPE], "LIST"))
7318             {
7319               sprintf(filter, "(&(objectClass=group)(cn=%s))", 
7320                       av[CONTAINER_ID]);
7321             }
7322
7323           if (strlen(filter) != 0)
7324             {
7325               attr_array[0] = "distinguishedName";
7326               attr_array[1] = NULL;
7327               group_count = 0;
7328               group_base = NULL;
7329               if ((rc = linklist_build(ldap_handle, dn_path, filter, 
7330                                        attr_array, 
7331                                        &group_base, &group_count, 
7332                                        LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7333                 {
7334                   if (group_count == 1)
7335                     {
7336                       strcpy(managedByDN, group_base->value);
7337                       managedBy_v[0] = managedByDN;
7338                       ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_ADD);
7339                     }
7340                   linklist_free(group_base);
7341                   group_base = NULL;
7342                   group_count = 0;
7343                 }
7344             }
7345         }
7346     }
7347   
7348   mods[n] = NULL;
7349
7350   sprintf(temp, "%s,%s", dName, dn_path);
7351   rc = ldap_add_ext_s(ldap_handle, temp, mods, NULL, NULL);
7352   
7353   for (i = 0; i < n; i++)
7354     free(mods[i]);
7355   
7356   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
7357     {
7358       com_err(whoami, 0, "Unable to create container %s : %s",
7359               cName, ldap_err2string(rc));
7360       return(rc);
7361     }
7362
7363   if (rc == LDAP_ALREADY_EXISTS)
7364     {
7365       if (strlen(av[CONTAINER_ROWID]) != 0)
7366         rc = container_adupdate(ldap_handle, dn_path, dName, "", count, av);
7367     }
7368
7369   return(rc);
7370 }
7371
7372 int container_update(LDAP *ldap_handle, char *dn_path, int beforec, 
7373                      char **before, int afterc, char **after)
7374 {
7375   char distinguishedName[256];
7376   int  rc;
7377
7378   memset(distinguishedName, '\0', sizeof(distinguishedName));
7379
7380   if (rc = container_get_distinguishedName(ldap_handle, dn_path, 
7381                                            distinguishedName, afterc, after))
7382     return(rc);
7383
7384   if (strlen(distinguishedName) == 0)
7385     {
7386       rc = container_create(ldap_handle, dn_path, afterc, after);
7387       return(rc);
7388     }
7389   
7390   container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
7391   rc = container_adupdate(ldap_handle, dn_path, "", distinguishedName, afterc,
7392                           after);
7393
7394   return(rc);
7395 }
7396
7397 int container_get_distinguishedName(LDAP *ldap_handle, char *dn_path, 
7398                                     char *distinguishedName, int count, 
7399                                     char **av)
7400 {
7401   char      *attr_array[3];
7402   LK_ENTRY  *group_base;
7403   int       group_count;
7404   char      dName[256];
7405   char      cName[256];
7406   char      filter[512];
7407   int       rc;
7408
7409   memset(filter, '\0', sizeof(filter));
7410   memset(dName, '\0', sizeof(dName));
7411   memset(cName, '\0', sizeof(cName));
7412   container_get_dn(av[CONTAINER_NAME], dName);
7413   container_get_name(av[CONTAINER_NAME], cName);
7414
7415   if (strlen(dName) == 0)
7416     {
7417       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", 
7418               av[CONTAINER_NAME]);
7419       return(AD_INVALID_NAME);
7420     }
7421
7422   if (!check_container_name(cName))
7423     {
7424       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", 
7425               cName);
7426       return(AD_INVALID_NAME);
7427     }
7428   
7429   sprintf(filter, "(&(objectClass=organizationalUnit)(mitMoiraId=%s))", 
7430           av[CONTAINER_ROWID]);
7431   attr_array[0] = "distinguishedName";
7432   attr_array[1] = NULL;
7433   group_count = 0;
7434   group_base = NULL;
7435
7436   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
7437                            &group_base, &group_count, 
7438                            LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7439     {
7440       if (group_count == 1)
7441         {
7442           strcpy(distinguishedName, group_base->value);
7443         }
7444
7445       linklist_free(group_base);
7446       group_base = NULL;
7447       group_count = 0;
7448     }
7449
7450   if (strlen(distinguishedName) == 0)
7451     {
7452       sprintf(filter, "(&(objectClass=organizationalUnit)"
7453               "(distinguishedName=%s,%s))", dName, dn_path);
7454       attr_array[0] = "distinguishedName";
7455       attr_array[1] = NULL;
7456       group_count = 0;
7457       group_base = NULL;
7458
7459       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
7460                                &group_base, &group_count, 
7461                                LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7462         {
7463           if (group_count == 1)
7464             {
7465               strcpy(distinguishedName, group_base->value);
7466             }
7467
7468           linklist_free(group_base);
7469           group_base = NULL;
7470           group_count = 0;
7471         }
7472     }
7473
7474   return(0);
7475 }
7476
7477 int container_adupdate(LDAP *ldap_handle, char *dn_path, char *dName, 
7478                        char *distinguishedName, int count, char **av)
7479 {
7480   char      *attr_array[5];
7481   LK_ENTRY  *group_base;
7482   LK_ENTRY  *pPtr;
7483   LDAPMod   *mods[20];
7484   int       group_count;
7485   char      filter[512];
7486   char      *moiraId_v[] = {NULL, NULL};
7487   char      *desc_v[] = {NULL, NULL};
7488   char      *managedBy_v[] = {NULL, NULL};
7489   char      managedByDN[256];
7490   char      moiraId[64];
7491   char      desc[256];
7492   char      ad_path[512];
7493   int       rc;
7494   int       i;
7495   int       n;
7496
7497
7498   strcpy(ad_path, distinguishedName);
7499
7500   if (strlen(dName) != 0)
7501     sprintf(ad_path, "%s,%s", dName, dn_path);
7502
7503   sprintf(filter, "(&(objectClass=organizationalUnit)(distinguishedName=%s))",
7504           ad_path);
7505
7506   if (strlen(av[CONTAINER_ID]) != 0)
7507     sprintf(filter, "(&(objectClass=organizationalUnit)(mitMoiraId=%s))", 
7508             av[CONTAINER_ROWID]);
7509
7510   attr_array[0] = "mitMoiraId";
7511   attr_array[1] = "description";
7512   attr_array[2] = "managedBy";
7513   attr_array[3] = NULL;
7514   group_count = 0;
7515   group_base = NULL;
7516
7517   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
7518                            &group_base, &group_count, 
7519                            LDAP_SCOPE_SUBTREE)) != LDAP_SUCCESS)
7520     {
7521       com_err(whoami, 0, "Unable to retreive container info for %s : %s",
7522               av[CONTAINER_NAME], ldap_err2string(rc));
7523       return(rc);
7524     }
7525
7526   memset(managedByDN, '\0', sizeof(managedByDN));
7527   memset(moiraId, '\0', sizeof(moiraId));
7528   memset(desc, '\0', sizeof(desc));
7529   pPtr = group_base;
7530
7531   while (pPtr)
7532     {
7533       if (!strcasecmp(pPtr->attribute, "description"))
7534         strcpy(desc, pPtr->value);
7535       else if (!strcasecmp(pPtr->attribute, "managedBy"))
7536         strcpy(managedByDN, pPtr->value);
7537       else if (!strcasecmp(pPtr->attribute, "mitMoiraId"))
7538         strcpy(moiraId, pPtr->value);
7539       pPtr = pPtr->next;
7540     }
7541
7542   linklist_free(group_base);
7543   group_base = NULL;
7544   group_count = 0;
7545
7546   n = 0;
7547   if (strlen(av[CONTAINER_ROWID]) != 0)
7548     {
7549       moiraId_v[0] = av[CONTAINER_ROWID];
7550       ADD_ATTR("mitMoiraId", moiraId_v, LDAP_MOD_REPLACE);
7551     }
7552
7553   if (strlen(av[CONTAINER_DESC]) != 0)
7554     {
7555       attribute_update(ldap_handle, ad_path, av[CONTAINER_DESC], "description",
7556                        dName);
7557     }
7558   else
7559     {
7560       if (strlen(desc) != 0)
7561         {
7562           attribute_update(ldap_handle, ad_path, "", "description", dName);
7563         }
7564     }
7565
7566   if ((strlen(av[CONTAINER_TYPE]) != 0) && (strlen(av[CONTAINER_ID]) != 0))
7567     {
7568       if (!strcasecmp(av[CONTAINER_TYPE], "KERBEROS"))
7569         {
7570           if (!contact_create(ldap_handle, dn_path, av[CONTAINER_ID], 
7571                               kerberos_ou))
7572             {
7573               sprintf(managedByDN, "CN=%s,%s,%s", av[CONTAINER_ID], 
7574                       kerberos_ou, dn_path);
7575               managedBy_v[0] = managedByDN;
7576               ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_REPLACE);
7577             }
7578           else
7579             {
7580               if (strlen(managedByDN) != 0)
7581                 {
7582                   attribute_update(ldap_handle, ad_path, "", "managedBy", 
7583                                    dName);
7584                 }
7585             }
7586         }
7587       else
7588         {
7589           memset(filter, '\0', sizeof(filter));
7590
7591           if (!strcasecmp(av[CONTAINER_TYPE], "USER"))
7592             {
7593               sprintf(filter, "(&(cn=%s)(&(objectCategory=person)"
7594                       "(objectClass=user)))", av[CONTAINER_ID]);
7595             }
7596
7597           if (!strcasecmp(av[CONTAINER_TYPE], "LIST"))
7598             {
7599               sprintf(filter, "(&(objectClass=group)(cn=%s))", 
7600                       av[CONTAINER_ID]);
7601             }
7602
7603           if (strlen(filter) != 0)
7604             {
7605               attr_array[0] = "distinguishedName";
7606               attr_array[1] = NULL;
7607               group_count = 0;
7608               group_base = NULL;
7609               if ((rc = linklist_build(ldap_handle, dn_path, filter, 
7610                                        attr_array, &group_base, &group_count, 
7611                                        LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7612                 {
7613                   if (group_count == 1)
7614                     {
7615                       strcpy(managedByDN, group_base->value);
7616                       managedBy_v[0] = managedByDN;
7617                       ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_REPLACE);
7618                     }
7619                   else
7620                     {
7621                       if (strlen(managedByDN) != 0)
7622                         {
7623                           attribute_update(ldap_handle, ad_path, "", 
7624                                            "managedBy", dName);
7625                         }
7626                     }
7627
7628                   linklist_free(group_base);
7629                   group_base = NULL;
7630                   group_count = 0;
7631                 }
7632             }
7633           else
7634             {
7635               if (strlen(managedByDN) != 0)
7636                 {
7637                   attribute_update(ldap_handle, ad_path, "", "managedBy", 
7638                                    dName);
7639                 }
7640             }
7641         }
7642     }
7643
7644   mods[n] = NULL;
7645
7646   if (n == 0)
7647     return(LDAP_SUCCESS);
7648
7649   rc = ldap_modify_s(ldap_handle, ad_path, mods);
7650
7651   for (i = 0; i < n; i++)
7652     free(mods[i]);
7653
7654   if (rc != LDAP_SUCCESS)
7655     {
7656       com_err(whoami, 0, "Unable to modify container info for %s : %s",
7657               av[CONTAINER_NAME], ldap_err2string(rc));
7658       return(rc);
7659     }
7660   
7661   return(rc);
7662 }
7663
7664 int container_move_objects(LDAP *ldap_handle, char *dn_path, char *dName)
7665 {
7666   char      *attr_array[3];
7667   LK_ENTRY  *group_base;
7668   LK_ENTRY  *pPtr;
7669   int       group_count;
7670   char      filter[512];
7671   char      new_cn[128];
7672   char      temp[256];
7673   int       rc;
7674   int       NumberOfEntries = 10;
7675   int       i;
7676   int       count;
7677
7678   rc = ldap_set_option(ldap_handle, LDAP_OPT_SIZELIMIT, &NumberOfEntries);
7679
7680   for (i = 0; i < 3; i++)
7681     {
7682       memset(filter, '\0', sizeof(filter));
7683
7684       if (i == 0)
7685         {
7686           strcpy(filter, "(!(|(objectClass=computer)"
7687                  "(objectClass=organizationalUnit)))");
7688           attr_array[0] = "cn";
7689           attr_array[1] = NULL;
7690         }
7691       else if (i == 1)
7692         {
7693           strcpy(filter, "(objectClass=computer)");
7694           attr_array[0] = "cn";
7695           attr_array[1] = NULL;
7696         }
7697       else
7698         {
7699           strcpy(filter, "(objectClass=organizationalUnit)");
7700           attr_array[0] = "ou";
7701           attr_array[1] = NULL;
7702         }
7703
7704       while (1)
7705         {
7706           if ((rc = linklist_build(ldap_handle, dName, filter, attr_array, 
7707                                    &group_base, &group_count, 
7708                                    LDAP_SCOPE_SUBTREE)) != LDAP_SUCCESS)
7709             {
7710               break;
7711             }
7712
7713           if (group_count == 0)
7714             break;
7715
7716           pPtr = group_base;
7717
7718           while(pPtr)
7719             {
7720               if (!strcasecmp(pPtr->attribute, "cn"))
7721                 {
7722                   sprintf(new_cn, "cn=%s", pPtr->value);
7723                   if (i == 0)
7724                     sprintf(temp, "%s,%s", orphans_other_ou, dn_path);
7725                   if (i == 1)
7726                     sprintf(temp, "%s,%s", orphans_machines_ou, dn_path);
7727                   count = 1;
7728
7729                   while (1)
7730                     {
7731                       rc = ldap_rename_s(ldap_handle, pPtr->dn, new_cn, temp,
7732                                          TRUE, NULL, NULL);
7733                       if (rc == LDAP_ALREADY_EXISTS)
7734                         {
7735                           sprintf(new_cn, "cn=%s_%d", pPtr->value, count);
7736                           ++count;
7737                         }
7738                       else
7739                         break;
7740                     }
7741                 }
7742               else if (!strcasecmp(pPtr->attribute, "ou"))
7743                 {
7744                   rc = ldap_delete_s(ldap_handle, pPtr->dn);
7745                 }
7746
7747               pPtr = pPtr->next;
7748             }
7749
7750           linklist_free(group_base);
7751           group_base = NULL;
7752           group_count = 0;
7753         }
7754     }
7755
7756   return(0);
7757 }
7758
7759 int get_machine_ou(LDAP *ldap_handle, char *dn_path, char *member, 
7760                    char *machine_ou, char *NewMachineName)
7761 {
7762   LK_ENTRY  *group_base;
7763   int  group_count;
7764   int  i;
7765   char filter[128];
7766   char *attr_array[3];
7767   char cn[256];
7768   char dn[256];
7769   char temp[256];
7770   char *pPtr;
7771   int   rc;
7772
7773   strcpy(NewMachineName, member);
7774   rc = moira_connect();
7775   rc = GetMachineName(NewMachineName);
7776   moira_disconnect();
7777
7778   if (strlen(NewMachineName) == 0)
7779     {
7780       com_err(whoami, 0, "Unable to find alais for machine %s in Moira", 
7781               member);
7782       return(1);
7783     }
7784
7785   pPtr = NULL;
7786   pPtr = strchr(NewMachineName, '.');
7787
7788   if (pPtr != NULL)
7789     (*pPtr) = '\0';
7790
7791   group_base = NULL;
7792   group_count = 0;
7793   sprintf(filter, "(sAMAccountName=%s$)", NewMachineName);
7794   attr_array[0] = "cn";
7795   attr_array[1] = NULL;
7796   sprintf(temp, "%s", dn_path);
7797
7798   if ((rc = linklist_build(ldap_handle, temp, filter, attr_array, 
7799                            &group_base, &group_count, 
7800                            LDAP_SCOPE_SUBTREE)) != 0)
7801     {
7802       com_err(whoami, 0, "Unable to process machine %s : %s",
7803               member, ldap_err2string(rc));
7804       return(1);
7805     }
7806
7807   if (group_count != 1)
7808     {
7809       return(1);
7810     }
7811
7812   strcpy(dn, group_base->dn);
7813   strcpy(cn, group_base->value);
7814
7815   for (i = 0; i < (int)strlen(dn); i++)
7816     dn[i] = tolower(dn[i]);
7817
7818   for (i = 0; i < (int)strlen(cn); i++)
7819     cn[i] = tolower(cn[i]);
7820
7821   linklist_free(group_base);
7822   pPtr = NULL;
7823   pPtr = strstr(dn, cn);
7824
7825   if (pPtr == NULL)
7826     {
7827       com_err(whoami, 0, "Unable to process machine %s",
7828               member);
7829       return(1);
7830     }
7831
7832   pPtr += strlen(cn) + 1;
7833   strcpy(machine_ou, pPtr);
7834   pPtr = NULL;
7835   pPtr = strstr(machine_ou, "dc=");
7836
7837   if (pPtr == NULL)
7838     {
7839       com_err(whoami, 0, "Unable to process machine %s",
7840               member);
7841       return(1);
7842     }
7843
7844   --pPtr;
7845   (*pPtr) = '\0';
7846
7847   return(0);
7848 }
7849
7850 int machine_move_to_ou(LDAP *ldap_handle, char * dn_path, 
7851                        char *MoiraMachineName, char *DestinationOu)
7852 {
7853   char        NewCn[128];
7854   char        OldDn[512];
7855   char        MachineName[128];
7856   char        filter[128];
7857   char        *attr_array[3];
7858   char        NewOu[256];
7859   char        *cPtr = NULL;
7860   int         group_count;
7861   long        rc;
7862   LK_ENTRY    *group_base;
7863
7864   group_count = 0;
7865   group_base = NULL;
7866   
7867   strcpy(MachineName, MoiraMachineName);
7868   rc = GetMachineName(MachineName);
7869
7870   if (strlen(MachineName) == 0)
7871     {
7872       com_err(whoami, 0, "Unable to find alais for machine %s in Moira", 
7873               MoiraMachineName);
7874       return(1);
7875     }
7876   
7877   cPtr = strchr(MachineName, '.');
7878
7879   if (cPtr != NULL)
7880     (*cPtr) = '\0';
7881
7882   sprintf(filter, "(sAMAccountName=%s$)", MachineName);
7883   attr_array[0] = "sAMAccountName";
7884   attr_array[1] = NULL;
7885
7886   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
7887                            &group_base, 
7888                            &group_count, LDAP_SCOPE_SUBTREE)) != 0)
7889     {
7890       com_err(whoami, 0, "Unable to process machine %s : %s",
7891               MoiraMachineName, ldap_err2string(rc));
7892       return(1);
7893     }
7894   
7895   if (group_count == 1)
7896     strcpy(OldDn, group_base->dn);
7897
7898   linklist_free(group_base);
7899   group_base = NULL;
7900
7901   if (group_count != 1)
7902     {
7903       com_err(whoami, 0, "Unable to find machine %s in directory: %s", 
7904               MoiraMachineName);
7905       return(1);
7906     }
7907
7908   sprintf(NewOu, "%s,%s", DestinationOu, dn_path);
7909   cPtr = strchr(OldDn, ',');
7910
7911   if (cPtr != NULL)
7912     {
7913       ++cPtr;
7914       if (!strcasecmp(cPtr, NewOu))
7915         return(0);
7916     }
7917
7918   sprintf(NewCn, "CN=%s", MachineName);
7919   rc = ldap_rename_s(ldap_handle, OldDn, NewCn, NewOu, TRUE, NULL, NULL);
7920
7921   return(rc);
7922 }
7923
7924 int machine_check(LDAP *ldap_handle, char *dn_path, char *machine_name)
7925 {
7926   char    Name[128];
7927   char    *pPtr;
7928   int     rc;
7929   
7930   memset(Name, '\0', sizeof(Name));
7931   strcpy(Name, machine_name);
7932   pPtr = NULL;
7933   pPtr = strchr(Name, '.');
7934
7935   if (pPtr != NULL)
7936     (*pPtr) = '\0';
7937
7938   strcat(Name, "$");
7939   return(!(rc = checkADname(ldap_handle, dn_path, Name)));
7940 }
7941
7942 int machine_get_moira_container(LDAP *ldap_handle, char *dn_path, 
7943                                 char *machine_name, char *container_name)
7944 {
7945   int     rc;
7946   char    *av[2];
7947   char    *call_args[2];
7948   
7949   av[0] = machine_name;
7950   call_args[0] = (char *)container_name;
7951   rc = mr_query("get_machine_to_container_map", 1, av, 
7952                 machine_GetMoiraContainer, call_args);
7953   return(rc);
7954 }
7955
7956 int machine_GetMoiraContainer(int ac, char **av, void *ptr)
7957 {
7958   char **call_args;
7959   
7960   call_args = ptr;
7961   strcpy(call_args[0], av[1]);
7962   return(0);
7963 }
7964
7965 int Moira_container_group_create(char **after)
7966 {
7967   long rc;
7968   char GroupName[64];
7969   char *argv[20];
7970   
7971   memset(GroupName, '\0', sizeof(GroupName));
7972   rc = Moira_groupname_create(GroupName, after[CONTAINER_NAME], 
7973                               after[CONTAINER_ROWID]);
7974   if (rc)
7975     return rc;
7976   
7977   argv[L_NAME] = GroupName;
7978   argv[L_ACTIVE] = "1";
7979   argv[L_PUBLIC] = "0";
7980   argv[L_HIDDEN] = "0";
7981   argv[L_MAILLIST] = "0";
7982   argv[L_GROUP] = "1";
7983   argv[L_GID] = UNIQUE_GID;
7984   argv[L_NFSGROUP] = "0";
7985   argv[L_MAILMAN] = "0";
7986   argv[L_MAILMAN_SERVER] = "[NONE]";
7987   argv[L_DESC] = "auto created container group";
7988   argv[L_ACE_TYPE] = "USER";
7989   argv[L_MEMACE_TYPE] = "USER";
7990   argv[L_ACE_NAME] = "sms";
7991   argv[L_MEMACE_NAME] = "sms";
7992
7993   if (rc = mr_query("add_list", 15, argv, NULL, NULL))
7994     {
7995       com_err(whoami, 0, 
7996               "Unable to create container group %s for container %s: %s",
7997               GroupName, after[CONTAINER_NAME], error_message(rc));
7998     }
7999
8000   Moira_setContainerGroup(after[CONTAINER_NAME], GroupName);
8001   Moira_addGroupToParent(after[CONTAINER_NAME], GroupName);
8002   
8003   return(rc);
8004 }
8005
8006 int Moira_container_group_update(char **before, char **after)
8007 {
8008   long rc;
8009   char BeforeGroupName[64];
8010   char AfterGroupName[64];
8011   char *argv[20];
8012   
8013   if (!strcasecmp(after[CONTAINER_NAME], before[CONTAINER_NAME]))
8014     return(0);
8015
8016   memset(BeforeGroupName, '\0', sizeof(BeforeGroupName));
8017   Moira_getGroupName(after[CONTAINER_NAME], BeforeGroupName, 0);
8018   if (strlen(BeforeGroupName) == 0)
8019     return(0);
8020
8021   memset(AfterGroupName, '\0', sizeof(AfterGroupName));
8022   rc = Moira_groupname_create(AfterGroupName, after[CONTAINER_NAME], 
8023                               after[CONTAINER_ROWID]);
8024   if (rc)
8025     return rc;
8026
8027   if (strcasecmp(BeforeGroupName, AfterGroupName))
8028     {
8029       argv[L_NAME] = BeforeGroupName;
8030       argv[L_NAME + 1] = AfterGroupName;
8031       argv[L_ACTIVE + 1] = "1";
8032       argv[L_PUBLIC + 1] = "0";
8033       argv[L_HIDDEN + 1] = "0";
8034       argv[L_MAILLIST + 1] = "0";
8035       argv[L_GROUP + 1] = "1";
8036       argv[L_GID + 1] = UNIQUE_GID;
8037       argv[L_NFSGROUP + 1] = "0";
8038       argv[L_MAILMAN + 1] = "0";
8039       argv[L_MAILMAN_SERVER + 1] = "[NONE]";
8040       argv[L_DESC + 1] = "auto created container group";
8041       argv[L_ACE_TYPE + 1] = "USER";
8042       argv[L_MEMACE_TYPE + 1] = "USER";
8043       argv[L_ACE_NAME + 1] = "sms";
8044       argv[L_MEMACE_NAME + 1] = "sms";
8045       
8046       if (rc = mr_query("update_list", 16, argv, NULL, NULL))
8047         {
8048           com_err(whoami, 0, 
8049                   "Unable to rename container group from %s to %s: %s",
8050                   BeforeGroupName, AfterGroupName, error_message(rc));
8051         }
8052     }
8053   
8054   return(rc);
8055 }
8056
8057 int Moira_container_group_delete(char **before)
8058 {
8059   long rc = 0;
8060   char *argv[13];
8061   char GroupName[64];
8062   char ParentGroupName[64];
8063   
8064   memset(ParentGroupName, '\0', sizeof(ParentGroupName));
8065   Moira_getGroupName(before[CONTAINER_NAME], ParentGroupName, 1);
8066
8067   memset(GroupName, '\0', sizeof(GroupName));
8068
8069   if (strcmp(before[CONTAINER_GROUP_NAME], "[none]"))
8070     strcpy(GroupName, before[CONTAINER_GROUP_NAME]);
8071   
8072   if ((strlen(ParentGroupName) != 0) && (strlen(GroupName) != 0))
8073     {
8074       argv[0] = ParentGroupName;
8075       argv[1] = "LIST";
8076       argv[2] = GroupName;
8077
8078       if (rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL))
8079         {
8080           com_err(whoami, 0, 
8081                   "Unable to delete container group %s from list: %s",
8082                   GroupName, ParentGroupName, error_message(rc));
8083         }
8084     }
8085   
8086   if (strlen(GroupName) != 0)
8087     {
8088       argv[0] = GroupName;
8089
8090       if (rc = mr_query("delete_list", 1, argv, NULL, NULL))
8091         {
8092           com_err(whoami, 0, "Unable to delete container group %s : %s",
8093                   GroupName, error_message(rc));
8094         }
8095     }
8096   
8097   return(rc);
8098 }
8099
8100 int Moira_groupname_create(char *GroupName, char *ContainerName,
8101                            char *ContainerRowID)
8102 {
8103   char *ptr;
8104   char *ptr1;
8105   char temp[64];
8106   char newGroupName[64];
8107   char tempGroupName[64];
8108   char tempgname[64];
8109   char *argv[1];
8110   int  i;
8111   long rc;
8112
8113   strcpy(temp, ContainerName);
8114   
8115   ptr1 = strrchr(temp, '/');
8116
8117   if (ptr1 != NULL)
8118   {
8119     *ptr1 = '\0';
8120     ptr = ++ptr1;
8121     ptr1 = strrchr(temp, '/');
8122
8123     if (ptr1 != NULL)
8124     {
8125         sprintf(tempgname, "%s-%s", ++ptr1, ptr);
8126     }
8127     else
8128         strcpy(tempgname, ptr);
8129   }
8130   else
8131     strcpy(tempgname, temp);
8132
8133   if (strlen(tempgname) > 25)
8134     tempgname[25] ='\0';
8135
8136   sprintf(newGroupName, "cnt-%s", tempgname);
8137
8138   /* change everything to lower case */
8139   ptr = newGroupName;
8140
8141   while (*ptr)
8142     {
8143       if (isupper(*ptr))
8144         *ptr = tolower(*ptr);
8145
8146       if (*ptr == ' ')
8147         *ptr = '-';
8148
8149       ptr++;
8150     }
8151
8152   strcpy(tempGroupName, newGroupName);
8153   i = (int)'0';
8154
8155   /* append 0-9 then a-z if a duplicate is found */
8156   while(1)
8157     {
8158       argv[0] = newGroupName;
8159
8160       if (rc = mr_query("get_list_info", 1, argv, NULL, NULL))
8161         {
8162           if (rc == MR_NO_MATCH)
8163             break;
8164           com_err(whoami, 0, "Moira error while creating group name for "
8165                   "container %s : %s", ContainerName, error_message(rc));
8166           return rc;
8167         }
8168
8169       sprintf(newGroupName, "%s-%c", tempGroupName, i);
8170
8171       if (i == (int)'z')
8172         {
8173           com_err(whoami, 0, "Unable to find a unique group name for "
8174                   "container %s: too many duplicate container names",
8175                   ContainerName);
8176           return 1;
8177         }
8178
8179       if (i == '9')
8180         i = 'a';
8181       else
8182         i++;
8183     }
8184
8185   strcpy(GroupName, newGroupName);
8186   return(0);
8187 }
8188
8189 int Moira_setContainerGroup(char *origContainerName, char *GroupName)
8190 {
8191   long rc;
8192   char *argv[3];
8193   
8194   argv[0] = origContainerName;
8195   argv[1] = GroupName;
8196   
8197   if ((rc = mr_query("set_container_list", 2, argv, NULL, NULL)))
8198     {
8199       com_err(whoami, 0, 
8200               "Unable to set container group %s in container %s: %s",
8201               GroupName, origContainerName, error_message(rc));
8202     }
8203   
8204   return(0);
8205 }
8206
8207 int Moira_addGroupToParent(char *origContainerName, char *GroupName)
8208  {
8209    char ContainerName[64];
8210    char ParentGroupName[64];
8211    char *argv[3];
8212    long rc;
8213
8214    strcpy(ContainerName, origContainerName);
8215    
8216    Moira_getGroupName(ContainerName, ParentGroupName, 1);
8217
8218    /* top-level container */
8219    if (strlen(ParentGroupName) == 0)
8220      return(0);
8221    
8222    argv[0] = ParentGroupName;
8223    argv[1] = "LIST";
8224    argv[2] = GroupName;
8225
8226    if ((rc = mr_query("add_member_to_list", 3, argv, NULL, NULL)))
8227      {
8228        com_err(whoami, 0, 
8229                "Unable to add container group %s to parent group %s: %s",
8230                GroupName, ParentGroupName, error_message(rc));
8231      }
8232    
8233    return(0);
8234  }
8235
8236 int Moira_getContainerGroup(int ac, char **av, void *ptr)
8237 {
8238   char **call_args;
8239   
8240   call_args = ptr;
8241   strcpy(call_args[0], av[1]);
8242
8243   return(0);
8244 }
8245
8246 int Moira_getGroupName(char *origContainerName, char *GroupName,
8247                        int ParentFlag)
8248 {
8249   char ContainerName[64];
8250   char *argv[3];
8251   char *call_args[3];
8252   char *ptr;
8253   long rc;
8254
8255   strcpy(ContainerName, origContainerName);
8256
8257   if (ParentFlag)
8258     {
8259       ptr = strrchr(ContainerName, '/');
8260
8261       if (ptr != NULL)
8262         (*ptr) = '\0';
8263       else
8264         return(0);
8265     }
8266
8267   argv[0] = ContainerName;
8268   argv[1] = NULL;
8269   call_args[0] = GroupName;
8270   call_args[1] = NULL;
8271
8272   if (!(rc = mr_query("get_container_list", 1, argv, Moira_getContainerGroup,
8273                       call_args)))
8274     {
8275       if (strlen(GroupName) != 0)
8276         return(0);
8277     }
8278
8279   if (rc)
8280     com_err(whoami, 0, "Unable to get container group from container %s: %s",
8281             ContainerName, error_message(rc));
8282   else
8283     com_err(whoami, 0, "Unable to get container group from container %s",
8284             ContainerName);
8285   
8286   return(0);
8287 }
8288
8289 int Moira_process_machine_container_group(char *MachineName, char* GroupName, 
8290                                           int DeleteMachine)
8291 {
8292   char *argv[3];
8293   long rc;
8294   
8295   if (strcmp(GroupName, "[none]") == 0)
8296     return 0;
8297
8298   argv[0] = GroupName;
8299   argv[1] = "MACHINE";
8300   argv[2] = MachineName;
8301
8302   if (!DeleteMachine)
8303     rc = mr_query("add_member_to_list", 3, argv, NULL, NULL);
8304   else
8305     rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL);
8306
8307   if (rc)
8308     {
8309       com_err(whoami, 0, "Unable to add machine %s to container group%s: %s",
8310               MachineName, GroupName, error_message(rc));
8311     }
8312
8313   return(0);
8314 }
8315
8316 int GetMachineName(char *MachineName)
8317 {
8318   char    *args[2];
8319   char    NewMachineName[1024];
8320   char    *szDot;
8321   int     rc = 0;
8322   int     i;
8323   DWORD   dwLen = 0;
8324   char    *call_args[2];
8325   
8326   // If the address happens to be in the top-level MIT domain, great!
8327   strcpy(NewMachineName, MachineName);
8328
8329   for (i = 0; i < (int)strlen(NewMachineName); i++)
8330     NewMachineName[i] = toupper(NewMachineName[i]);
8331
8332   szDot = strchr(NewMachineName,'.');
8333
8334   if ((szDot) && (!strcasecmp(szDot+1, DOMAIN_SUFFIX)))
8335     {
8336       return(0);
8337     }
8338   
8339   // If not, see if it has a Moira alias in the top-level MIT domain.
8340   memset(NewMachineName, '\0', sizeof(NewMachineName));
8341   args[0] = "*";
8342   args[1] = MachineName;
8343   call_args[0] = NewMachineName;
8344   call_args[1] = NULL;
8345
8346   if (rc = mr_query("get_hostalias", 2, args, ProcessMachineName, call_args))
8347     {
8348       com_err(whoami, 0, "Unable to resolve machine name %s : %s",
8349               MachineName, error_message(rc));
8350       strcpy(MachineName, "");
8351       return(0);
8352     }
8353   
8354   if (strlen(NewMachineName) != 0)
8355     strcpy(MachineName, NewMachineName);
8356   else
8357     strcpy(MachineName, "");
8358
8359   return(0);
8360 }
8361
8362 int ProcessMachineName(int ac, char **av, void *ptr)
8363 {
8364   char    **call_args;
8365   char    MachineName[1024];
8366   char    *szDot;
8367   int     i;
8368   
8369   call_args = ptr;
8370
8371   if (strlen(call_args[0]) == 0)
8372     {
8373       strcpy(MachineName, av[0]);
8374
8375       for (i = 0; i < (int)strlen(MachineName); i++)
8376         MachineName[i] = toupper(MachineName[i]);
8377
8378       szDot = strchr(MachineName,'.');
8379
8380         if ((szDot) && (!strcasecmp(szDot+1,DOMAIN_SUFFIX)))
8381           {
8382             strcpy(call_args[0], MachineName);
8383           }
8384     }
8385
8386   return(0);
8387 }
8388
8389 void SwitchSFU(LDAPMod **mods, int *UseSFU30, int n)
8390 {
8391   int i;
8392   
8393   if (*UseSFU30)
8394     {
8395       for (i = 0; i < n; i++)
8396         {
8397           if (!strcmp(mods[i]->mod_type, "msSFU30UidNumber"))
8398             mods[i]->mod_type = "uidNumber";
8399         }
8400
8401       (*UseSFU30) = 0;
8402     }
8403   else
8404     {
8405       for (i = 0; i < n; i++)
8406         {
8407           if (!strcmp(mods[i]->mod_type, "uidNumber"))
8408             mods[i]->mod_type = "msSFU30UidNumber";
8409         }
8410
8411       (*UseSFU30) = 1;
8412     }
8413 }
8414
8415 int SetHomeDirectory(LDAP *ldap_handle, char *user_name, 
8416                      char *DistinguishedName,
8417                      char *WinHomeDir, char *WinProfileDir,
8418                      char **homedir_v, char **winProfile_v,
8419                      char **drives_v, LDAPMod **mods, 
8420                      int OpType, int n)
8421 {
8422   char cWeight[3];
8423   char cPath[1024];
8424   char path[1024];
8425   char winPath[1024];
8426   char winProfile[1024];
8427   char homeDrive[8];
8428   char homedir[1024];
8429   char apple_homedir[1024];
8430   char *apple_homedir_v[] = {NULL, NULL};
8431   int  last_weight;
8432   int  i;
8433   int  rc;
8434   LDAPMod *DelMods[20];
8435   char *argv[3];
8436   char *save_argv[FS_END];
8437   char *fsgroup_save_argv[2];
8438
8439   memset(homeDrive, '\0', sizeof(homeDrive));
8440   memset(path, '\0', sizeof(path));
8441   memset(winPath, '\0', sizeof(winPath));
8442   memset(winProfile, '\0', sizeof(winProfile));
8443
8444   if(!ActiveDirectory) 
8445     {
8446       if (rc = moira_connect())
8447         {
8448           critical_alert("Ldap incremental",
8449                          "Error contacting Moira server : %s",
8450                          error_message(rc));
8451           return;
8452         }
8453       
8454       argv[0] = user_name;
8455
8456       if (!(rc = mr_query("get_filesys_by_label", 1, argv, save_query_info, 
8457                           save_argv)))
8458         {
8459           if(!strcmp(save_argv[FS_TYPE], "FSGROUP") ||
8460              !strcmp(save_argv[FS_TYPE], "MUL"))
8461             {
8462         
8463               argv[0] = save_argv[FS_NAME];
8464               fsgCount = 0;
8465               
8466               if (!(rc = mr_query("get_fsgroup_members", 1, argv, 
8467                                   save_fsgroup_info, fsgroup_save_argv)))
8468                 {
8469                   if(fsgCount)
8470                     {
8471                       argv[0] = fsgroup_save_argv[0];
8472                       
8473                       if (!(rc = mr_query("get_filesys_by_label", 1, argv, 
8474                                           save_query_info, save_argv)))
8475                         {
8476                           strcpy(path, save_argv[FS_PACK]);
8477                         }
8478                     }
8479                 }
8480             }
8481           else
8482             {
8483               strcpy(path, save_argv[FS_PACK]);
8484             }
8485         }
8486       
8487       moira_disconnect();
8488
8489       if (strlen(path))
8490         {
8491           if (!strnicmp(path, AFS, strlen(AFS)))
8492             {
8493               sprintf(homedir, "%s", path);
8494               sprintf(apple_homedir, "%s/MacData", path);
8495               homedir_v[0] = homedir;
8496               apple_homedir_v[0] = apple_homedir;
8497               ADD_ATTR("homeDirectory", homedir_v, OpType);
8498               ADD_ATTR("apple-user-homeDirectory", apple_homedir_v, 
8499                        OpType);
8500             }
8501         }
8502       else
8503         {
8504           homedir_v[0] = "NONE";
8505           apple_homedir_v[0] = "NONE";
8506           ADD_ATTR("homeDirectory", homedir_v, OpType);
8507           ADD_ATTR("apple-user-homeDirectory", apple_homedir_v, 
8508                    OpType);
8509         }
8510
8511       return(n);
8512     }
8513  
8514   if ((!strcasecmp(WinHomeDir, "[afs]")) || 
8515       (!strcasecmp(WinProfileDir, "[afs]")))
8516     {
8517       if (rc = moira_connect())
8518         {
8519           critical_alert("Ldap incremental",
8520                          "Error contacting Moira server : %s",
8521                          error_message(rc));
8522           return;
8523         }
8524       
8525       argv[0] = user_name;
8526
8527       if (!(rc = mr_query("get_filesys_by_label", 1, argv, save_query_info, 
8528                           save_argv)))
8529         {
8530           if(!strcmp(save_argv[FS_TYPE], "FSGROUP") ||
8531              !strcmp(save_argv[FS_TYPE], "MUL"))
8532             {
8533         
8534               argv[0] = save_argv[FS_NAME];
8535               fsgCount = 0;
8536               
8537               if (!(rc = mr_query("get_fsgroup_members", 1, argv, 
8538                                   save_fsgroup_info, fsgroup_save_argv)))
8539                 {
8540                   if(fsgCount)
8541                     {
8542                       argv[0] = fsgroup_save_argv[0];
8543                       
8544                       if (!(rc = mr_query("get_filesys_by_label", 1, argv, 
8545                                           save_query_info, save_argv)))
8546                         {
8547                           strcpy(path, save_argv[FS_PACK]);
8548                         }
8549                     }
8550                 }
8551             }
8552           else
8553             {
8554               strcpy(path, save_argv[FS_PACK]);
8555             }
8556         }
8557      
8558       moira_disconnect();
8559
8560       if (strlen(path))
8561         {
8562           if (!strnicmp(path, AFS, strlen(AFS)))
8563             {
8564               AfsToWinAfs(path, winPath);
8565               strcpy(winProfile, winPath);
8566               strcat(winProfile, "\\.winprofile");
8567             }
8568         }
8569       else
8570         return(n);
8571     }
8572
8573     if ((!strcasecmp(WinHomeDir, "[dfs]")) || 
8574         (!strcasecmp(WinProfileDir, "[dfs]")))
8575     {
8576       sprintf(path, "\\\\%s\\dfs\\profiles\\%c\\%s", ldap_domain, 
8577               user_name[0], user_name);
8578
8579       if (!strcasecmp(WinProfileDir, "[dfs]"))
8580         {
8581           strcpy(winProfile, path);
8582           strcat(winProfile, "\\.winprofile");
8583         }
8584
8585       if (!strcasecmp(WinHomeDir, "[dfs]"))
8586         strcpy(winPath, path);
8587     }
8588     
8589     if (!strcasecmp(WinHomeDir, "[local]"))
8590       memset(winPath, '\0', sizeof(winPath));
8591     else if (!strcasecmp(WinHomeDir, "[afs]") || 
8592              !strcasecmp(WinHomeDir, "[dfs]"))
8593       {
8594         strcpy(homeDrive, "H:");
8595       }
8596     else
8597       {
8598         strcpy(winPath, WinHomeDir);
8599         if (!strncmp(WinHomeDir, "\\\\", 2))
8600           {
8601             strcpy(homeDrive, "H:");
8602           }        
8603       }
8604     
8605     // nothing needs to be done if WinProfileDir is [afs].
8606     if (!strcasecmp(WinProfileDir, "[local]"))
8607       memset(winProfile, '\0', sizeof(winProfile));
8608     else if (strcasecmp(WinProfileDir, "[afs]") && 
8609              strcasecmp(WinProfileDir, "[dfs]"))
8610       {
8611         strcpy(winProfile, WinProfileDir);
8612       }
8613     
8614     if (strlen(winProfile) != 0)
8615       {
8616         if (winProfile[strlen(winProfile) - 1] == '\\')
8617           winProfile[strlen(winProfile) - 1] = '\0';
8618       }
8619
8620     if (strlen(winPath) != 0)
8621       {
8622         if (winPath[strlen(winPath) - 1] == '\\')
8623           winPath[strlen(winPath) - 1] = '\0';
8624       }
8625     
8626     if ((winProfile[1] == ':') && (strlen(winProfile) == 2))
8627       strcat(winProfile, "\\");
8628
8629     if ((winPath[1] == ':') && (strlen(winPath) == 2))
8630       strcat(winPath, "\\");
8631     
8632     if (strlen(winPath) == 0)
8633       {
8634         if (OpType == LDAP_MOD_REPLACE)
8635           {
8636             i = 0;
8637             DEL_ATTR("homeDirectory", LDAP_MOD_DELETE);
8638             DelMods[i] = NULL;
8639             //unset homeDirectory attribute for user.
8640             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
8641             free(DelMods[0]);
8642           }
8643       }
8644     else
8645       {
8646         homedir_v[0] = strdup(winPath);
8647         ADD_ATTR("homeDirectory", homedir_v, OpType);
8648       }
8649     
8650     if (strlen(winProfile) == 0)
8651       {
8652         if (OpType == LDAP_MOD_REPLACE)
8653           {
8654             i = 0;
8655             DEL_ATTR("profilePath", LDAP_MOD_DELETE);
8656             DelMods[i] = NULL;
8657             //unset profilePate attribute for user.
8658             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
8659             free(DelMods[0]);
8660           }
8661       }
8662     else
8663       {
8664         winProfile_v[0] = strdup(winProfile);
8665         ADD_ATTR("profilePath", winProfile_v, OpType);
8666       }
8667     
8668     if (strlen(homeDrive) == 0)
8669       {
8670         if (OpType == LDAP_MOD_REPLACE)
8671           {
8672             i = 0;
8673             DEL_ATTR("homeDrive", LDAP_MOD_DELETE);
8674             DelMods[i] = NULL;
8675             //unset homeDrive attribute for user
8676             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
8677             free(DelMods[0]);
8678           }
8679       }
8680     else
8681       {
8682         drives_v[0] = strdup(homeDrive);
8683         ADD_ATTR("homeDrive", drives_v, OpType);
8684       }
8685
8686     return(n);
8687 }
8688
8689 int attribute_update(LDAP *ldap_handle, char *distinguished_name, 
8690                      char *attribute_value, char *attribute, char *user_name)
8691 {
8692   char      *mod_v[] = {NULL, NULL};
8693   LDAPMod   *DelMods[20];
8694   LDAPMod   *mods[20];
8695   int       n;
8696   int       i;
8697   int       rc;
8698   
8699   if (strlen(attribute_value) == 0)
8700     {
8701       i = 0;
8702       DEL_ATTR(attribute, LDAP_MOD_DELETE);
8703       DelMods[i] = NULL;
8704       rc = ldap_modify_s(ldap_handle, distinguished_name, DelMods);
8705       free(DelMods[0]);
8706     }
8707   else
8708     {
8709       n = 0;
8710       mod_v[0] = attribute_value;
8711       ADD_ATTR(attribute, mod_v, LDAP_MOD_REPLACE);
8712       mods[n] = NULL;
8713
8714       if ((rc = ldap_modify_s(ldap_handle, distinguished_name, 
8715                               mods)) != LDAP_SUCCESS)
8716         {
8717           free(mods[0]);
8718           n = 0;
8719           mod_v[0] = attribute_value;
8720           ADD_ATTR(attribute, mod_v, LDAP_MOD_ADD);
8721           mods[n] = NULL;
8722
8723           if ((rc = ldap_modify_s(ldap_handle, distinguished_name, 
8724                                   mods)) != LDAP_SUCCESS)
8725             {
8726               com_err(whoami, 0, "Unable to change the %s attribute for %s "
8727                       "in the directory : %s",
8728                       attribute, user_name, ldap_err2string(rc));
8729             }
8730         }
8731
8732       free(mods[0]);
8733     }
8734   
8735   return(rc);
8736 }
8737
8738 void StringTrim(char *StringToTrim)
8739 {
8740   char *t, *s;
8741   char *save;
8742
8743   save = strdup(StringToTrim);
8744
8745   s = save;
8746
8747   while (isspace(*s))
8748     s++;
8749
8750   /* skip to end of string */
8751   if (*s == '\0')
8752     {
8753       if (*save)
8754         *save = '\0';
8755       strcpy(StringToTrim, save);
8756       return;
8757     }
8758   
8759   for (t = s; *t; t++)
8760     continue;
8761
8762   while (t > s)
8763     {
8764       --t;
8765       if (!isspace(*t))
8766         {
8767           t++;
8768           break;
8769         }
8770     }
8771
8772   if (*t)
8773     *t = '\0';
8774   
8775   strcpy(StringToTrim, s);
8776   return;
8777 }
8778
8779 int ReadConfigFile(char *DomainName)
8780 {
8781     int     Count;
8782     int     i;
8783     int     k;
8784     char    temp[256];
8785     char    temp1[256];
8786     FILE    *fptr;
8787
8788     Count = 0;
8789
8790     sprintf(temp, "%s%s.cfg", CFG_PATH, DomainName);
8791
8792     if ((fptr = fopen(temp, "r")) != NULL)
8793       {
8794         while (fgets(temp, sizeof(temp), fptr) != 0)
8795           {
8796             for (i = 0; i < (int)strlen(temp); i++)
8797               temp[i] = toupper(temp[i]);
8798
8799             if (temp[strlen(temp) - 1] == '\n')
8800               temp[strlen(temp) - 1] = '\0';
8801
8802             StringTrim(temp);
8803
8804             if (strlen(temp) == 0)
8805               continue;
8806
8807             if (!strncmp(temp, DOMAIN, strlen(DOMAIN)))
8808               {
8809                 if (strlen(temp) > (strlen(DOMAIN)))
8810                   {
8811                     strcpy(ldap_domain, &temp[strlen(DOMAIN)]);
8812                     StringTrim(ldap_domain);
8813                   }
8814               }
8815             else if (!strncmp(temp, REALM, strlen(REALM)))
8816               {
8817                 if (strlen(temp) > (strlen(REALM)))
8818                   {
8819                     strcpy(ldap_realm, &temp[strlen(REALM)]);
8820                     StringTrim(ldap_realm);
8821                   }
8822               }
8823             else if (!strncmp(temp, PORT, strlen(PORT)))
8824               {
8825                 if (strlen(temp) > (strlen(PORT)))
8826                   {
8827                     strcpy(ldap_port, &temp[strlen(PORT)]);
8828                     StringTrim(ldap_port);
8829                   }
8830               }
8831             else if (!strncmp(temp, PRINCIPALNAME, strlen(PRINCIPALNAME)))
8832               {
8833                 if (strlen(temp) > (strlen(PRINCIPALNAME)))
8834                   {
8835                     strcpy(PrincipalName, &temp[strlen(PRINCIPALNAME)]);
8836                     StringTrim(PrincipalName);
8837                   }
8838               }
8839             else if (!strncmp(temp, SERVER, strlen(SERVER)))
8840               {
8841                 if (strlen(temp) > (strlen(SERVER)))
8842                   {
8843                     ServerList[Count] = calloc(1, 256);
8844                     strcpy(ServerList[Count], &temp[strlen(SERVER)]);
8845                     StringTrim(ServerList[Count]);
8846                     ++Count;
8847                   }
8848               }
8849             else if (!strncmp(temp, MSSFU, strlen(MSSFU)))
8850               {
8851                 if (strlen(temp) > (strlen(MSSFU)))
8852                   {
8853                     strcpy(temp1, &temp[strlen(MSSFU)]);
8854                     StringTrim(temp1);
8855                     if (!strcmp(temp1, SFUTYPE))
8856                       UseSFU30 = 1;
8857                   }
8858               }
8859             else if (!strncmp(temp, GROUP_SUFFIX, strlen(GROUP_SUFFIX)))
8860               {
8861                 if (strlen(temp) > (strlen(GROUP_SUFFIX)))
8862                   {
8863                     strcpy(temp1, &temp[strlen(GROUP_SUFFIX)]);
8864                     StringTrim(temp1);
8865                     if (!strcasecmp(temp1, "NO")) 
8866                       {
8867                         UseGroupSuffix = 0;
8868                         memset(group_suffix, '\0', sizeof(group_suffix));
8869                       }
8870                   }
8871               }
8872             else if (!strncmp(temp, GROUP_TYPE, strlen(GROUP_TYPE)))
8873               {
8874                 if (strlen(temp) > (strlen(GROUP_TYPE)))
8875                   {
8876                     strcpy(temp1, &temp[strlen(GROUP_TYPE)]);
8877                     StringTrim(temp1);
8878                     if (!strcasecmp(temp1, "UNIVERSAL")) 
8879                       UseGroupUniversal = 1;
8880                   }
8881               }
8882             else if (!strncmp(temp, SET_GROUP_ACE, strlen(SET_GROUP_ACE)))
8883               {
8884                 if (strlen(temp) > (strlen(SET_GROUP_ACE)))
8885                   {
8886                     strcpy(temp1, &temp[strlen(SET_GROUP_ACE)]);
8887                     StringTrim(temp1);
8888                     if (!strcasecmp(temp1, "NO"))
8889                       SetGroupAce = 0;
8890                   }
8891               }
8892             else if (!strncmp(temp, SET_PASSWORD, strlen(SET_PASSWORD)))
8893               {
8894                 if (strlen(temp) > (strlen(SET_PASSWORD)))
8895                   {
8896                     strcpy(temp1, &temp[strlen(SET_PASSWORD)]);
8897                     StringTrim(temp1);
8898                     if (!strcasecmp(temp1, "NO"))
8899                       SetPassword = 0;
8900                   }
8901               }
8902             else if (!strncmp(temp, EXCHANGE, strlen(EXCHANGE)))
8903               {
8904                 if (strlen(temp) > (strlen(EXCHANGE)))
8905                   {
8906                     strcpy(temp1, &temp[strlen(EXCHANGE)]);
8907                     StringTrim(temp1);
8908                     if (!strcasecmp(temp1, "YES"))
8909                       Exchange = 1;
8910                   }
8911               }
8912             else if (!strncmp(temp, PROCESS_MACHINE_CONTAINER, 
8913                               strlen(PROCESS_MACHINE_CONTAINER)))
8914               {
8915                 if (strlen(temp) > (strlen(PROCESS_MACHINE_CONTAINER)))
8916                   {
8917                     strcpy(temp1, &temp[strlen(PROCESS_MACHINE_CONTAINER)]);
8918                     StringTrim(temp1);
8919                     if (!strcasecmp(temp1, "NO"))
8920                       ProcessMachineContainer = 0;
8921                   }
8922               }
8923             else if (!strncmp(temp, ACTIVE_DIRECTORY, 
8924                               strlen(ACTIVE_DIRECTORY)))
8925               {
8926                 if (strlen(temp) > (strlen(ACTIVE_DIRECTORY)))
8927                   {
8928                     strcpy(temp1, &temp[strlen(ACTIVE_DIRECTORY)]);
8929                     StringTrim(temp1);
8930                     if (!strcasecmp(temp1, "NO"))
8931                       ActiveDirectory = 0;
8932                   }
8933               }
8934             else if (!strncmp(temp, GROUP_POPULATE_MEMBERS, 
8935                               strlen(GROUP_POPULATE_MEMBERS)))
8936               {
8937                 if (strlen(temp) > (strlen(GROUP_POPULATE_MEMBERS)))
8938                   {
8939                     strcpy(temp1, &temp[strlen(GROUP_POPULATE_MEMBERS)]);
8940                     StringTrim(temp1);
8941                     if (!strcasecmp(temp1, "DELETE")) 
8942                       {
8943                         GroupPopulateDelete = 1;
8944                       }
8945                   }
8946               }
8947             else if (!strncmp(temp, MAX_MEMBERS, strlen(MAX_MEMBERS)))
8948               {
8949                 if (strlen(temp) > (strlen(MAX_MEMBERS)))
8950                   {
8951                     strcpy(temp1, &temp[strlen(MAX_MEMBERS)]);
8952                     StringTrim(temp1);
8953                     max_group_members = atoi(temp1);
8954                   }
8955               }
8956             else
8957               {
8958                 if (strlen(ldap_domain) != 0)
8959                   {
8960                     memset(ldap_domain, '\0', sizeof(ldap_domain));
8961                     break;
8962                   }
8963
8964                 if (strlen(temp) != 0)
8965                   strcpy(ldap_domain, temp);
8966               }
8967           }
8968         fclose(fptr);
8969       }
8970     
8971     if (strlen(ldap_domain) == 0)
8972       {
8973       strcpy(ldap_domain, DomainName);
8974       }
8975
8976     if (Count == 0)
8977         return(0);
8978
8979     for (i = 0; i < Count; i++)
8980       {
8981         if (ServerList[i] != 0)
8982           {
8983             for (k = 0; k < (int)strlen(ServerList[i]); k++)
8984               ServerList[i][k] = toupper(ServerList[i][k]);
8985           }
8986       }
8987     
8988     return(0);
8989 }
8990
8991 int ReadDomainList()
8992 {
8993   int     Count;
8994   int     i;
8995   char    temp[128];
8996   char    temp1[128];
8997   FILE    *fptr;
8998   unsigned char c[11];
8999   unsigned char stuff[256];
9000   int     rc;
9001   int     ok;
9002
9003   Count = 0;
9004   sprintf(temp, "%s%s", CFG_PATH, WINADCFG);
9005
9006   if ((fptr = fopen(temp, "r")) != NULL)
9007     {
9008       while (fgets(temp, sizeof(temp), fptr) != 0)
9009         {
9010           for (i = 0; i < (int)strlen(temp); i++)
9011             temp[i] = toupper(temp[i]);
9012
9013           if (temp[strlen(temp) - 1] == '\n')
9014             temp[strlen(temp) - 1] = '\0';
9015
9016           StringTrim(temp);
9017
9018           if (strlen(temp) == 0)
9019             continue;
9020
9021           if (!strncmp(temp, DOMAIN, strlen(DOMAIN)))
9022             {
9023               if (strlen(temp) > (strlen(DOMAIN)))
9024                 {
9025                   strcpy(temp1, &temp[strlen(DOMAIN)]);
9026                   StringTrim(temp1);
9027                   strcpy(temp, temp1);
9028                 }
9029             }
9030           
9031           strcpy(DomainNames[Count], temp);
9032           StringTrim(DomainNames[Count]);
9033           ++Count;
9034         }
9035
9036       fclose(fptr);
9037     }
9038
9039   if (Count == 0)
9040     {
9041       critical_alert("incremental", "%s", "ldap.incr cannot run due to a "
9042                      "configuration error in ldap.cfg");
9043       return(1);
9044     }
9045   
9046   return(0);
9047 }
9048
9049 int email_isvalid(const char *address) {
9050   int        count = 0;
9051   const char *c, *domain;
9052   static char *rfc822_specials = "()<>@,;:\\\"[]";
9053
9054   if(address[strlen(address) - 1] == '.') 
9055     return 0;
9056     
9057   /* first we validate the name portion (name@domain) */
9058   for (c = address;  *c;  c++) {
9059     if (*c == '\"' && (c == address || *(c - 1) == '.' || *(c - 1) == 
9060                        '\"')) {
9061       while (*++c) {
9062         if (*c == '\"') 
9063           break;
9064         if (*c == '\\' && (*++c == ' ')) 
9065           continue;
9066         if (*c <= ' ' || *c >= 127) 
9067           return 0;
9068       }
9069
9070       if (!*c++) 
9071         return 0;
9072       if (*c == '@') 
9073         break;
9074       if (*c != '.') 
9075         return 0;
9076       continue;
9077     }
9078
9079     if (*c == '@') 
9080       break;
9081     if (*c <= ' ' || *c >= 127) 
9082       return 0;
9083     if (strchr(rfc822_specials, *c)) 
9084       return 0;
9085   }
9086
9087   if (c == address || *(c - 1) == '.') 
9088     return 0;
9089
9090   /* next we validate the domain portion (name@domain) */
9091   if (!*(domain = ++c)) return 0;
9092   do {
9093     if (*c == '.') {
9094       if (c == domain || *(c - 1) == '.') 
9095         return 0;
9096       count++;
9097     }
9098     if (*c <= ' ' || *c >= 127) 
9099       return 0;
9100     if (strchr(rfc822_specials, *c)) 
9101       return 0;
9102   } while (*++c);
9103
9104   return (count >= 1);
9105 }
9106
9107 int find_homeMDB(LDAP *ldap_handle, char *dn_path, char **homeMDB, 
9108              char **homeServerName) 
9109 {
9110   LK_ENTRY *group_base;
9111   LK_ENTRY *sub_group_base;
9112   LK_ENTRY *gPtr;
9113   LK_ENTRY *sub_gPtr;
9114   int      group_count;
9115   int      sub_group_count;
9116   char     filter[1024];
9117   char     sub_filter[1024];
9118   char     search_path[1024];
9119   char     range[1024];
9120   char     *attr_array[3];
9121   char     *s;
9122   int      homeMDB_count = -1;
9123   int      rc;
9124   int      i;
9125   int      mdbbl_count;
9126   int      rangeStep = 1500;
9127   int      rangeLow = 0;
9128   int      rangeHigh = rangeLow + (rangeStep - 1);
9129   int      isLast = 0;
9130
9131   /* Grumble..... microsoft not making it searchable from the root *grr* */
9132
9133   memset(filter, '\0', sizeof(filter));
9134   memset(search_path, '\0', sizeof(search_path));
9135   
9136   sprintf(filter, "(objectClass=msExchMDB)");
9137   sprintf(search_path, "CN=Configuration,%s", dn_path);
9138   attr_array[0] = "distinguishedName";
9139   attr_array[1] = NULL;
9140   
9141   group_base = NULL;
9142   group_count = 0;
9143   
9144   if ((rc = linklist_build(ldap_handle, search_path, filter, attr_array,
9145                            &group_base, &group_count, 
9146                            LDAP_SCOPE_SUBTREE)) != 0) 
9147     {
9148       com_err(whoami, 0, "Unable to find msExchMDB %s",
9149               ldap_err2string(rc));
9150       return(rc);
9151     }
9152   
9153   if (group_count) 
9154     {
9155       gPtr = group_base;
9156       
9157       while(gPtr) {
9158         if (((s = strstr(gPtr->dn, "Public")) != (char *) NULL) ||
9159             ((s = strstr(gPtr->dn, "Recover")) != (char *) NULL) || 
9160             ((s = strstr(gPtr->dn, "Reserve")) != (char *) NULL))
9161           {
9162             gPtr = gPtr->next;
9163             continue;
9164           }
9165
9166         /* 
9167          * Due to limits in active directory we need to use the LDAP
9168          * range semantics to query and return all the values in 
9169          * large lists, we will stop increasing the range when
9170          * the result count is 0.
9171          */
9172
9173         i = 0;  
9174         mdbbl_count = 0;
9175
9176         for(;;) 
9177           {
9178             memset(sub_filter, '\0', sizeof(sub_filter));
9179             memset(range, '\0', sizeof(range));
9180             sprintf(sub_filter, "(objectClass=msExchMDB)");
9181
9182             if(isLast)
9183               sprintf(range, "homeMDBBL;Range=%d-*", rangeLow);
9184             else 
9185               sprintf(range, "homeMDBBL;Range=%d-%d", rangeLow, rangeHigh);
9186
9187             attr_array[0] = range;
9188             attr_array[1] = NULL;
9189             
9190             sub_group_base = NULL;
9191             sub_group_count = 0;
9192             
9193             if ((rc = linklist_build(ldap_handle, gPtr->dn, sub_filter, 
9194                                      attr_array, &sub_group_base, 
9195                                      &sub_group_count, 
9196                                      LDAP_SCOPE_SUBTREE)) != 0) 
9197               {
9198                 com_err(whoami, 0, "Unable to find homeMDBBL %s",
9199                         ldap_err2string(rc));
9200                 return(rc);
9201               }
9202
9203             if(!sub_group_count)
9204               {
9205                 if(isLast) 
9206                   {
9207                     isLast = 0;
9208                     rangeLow = 0;
9209                     rangeHigh = rangeLow + (rangeStep - 1);
9210                     break;
9211                   }
9212                 else
9213                   isLast++;
9214               }
9215
9216             mdbbl_count += sub_group_count;
9217             rangeLow = rangeHigh + 1;
9218             rangeHigh = rangeLow + (rangeStep - 1);
9219           }
9220
9221         /* First time through, need to initialize or update the least used */
9222         
9223         com_err(whoami, 0, "Mail store %s, count %d", gPtr->dn, 
9224                 mdbbl_count);
9225
9226         if(mdbbl_count < homeMDB_count || homeMDB_count == -1) 
9227           {
9228             homeMDB_count = mdbbl_count; 
9229             *homeMDB = strdup(gPtr->dn);
9230           }
9231
9232         gPtr = gPtr->next;
9233         linklist_free(sub_group_base);
9234       }
9235     }
9236
9237   linklist_free(group_base);
9238   
9239   /* 
9240    * Ok found the server least allocated need to now query to get its
9241    * msExchHomeServerName so we can set it as a user attribute
9242    */
9243   
9244   attr_array[0] = "legacyExchangeDN";
9245   attr_array[1] = NULL; 
9246   
9247   group_count = 0;
9248   group_base = NULL;
9249   
9250   if ((rc = linklist_build(ldap_handle, *homeMDB, filter, 
9251                            attr_array, &group_base, 
9252                            &group_count, 
9253                            LDAP_SCOPE_SUBTREE)) != 0) 
9254     {
9255       com_err(whoami, 0, "Unable to find msExchHomeServerName %s",
9256               ldap_err2string(rc));
9257       return(rc);
9258     }  
9259   
9260   if(group_count) 
9261     {
9262       *homeServerName = strdup(group_base->value);
9263       if((s = strrchr(*homeServerName, '/')) != (char *) NULL) 
9264         {
9265           *s = '\0';
9266         }
9267     } 
9268
9269   linklist_free(group_base);
9270   
9271   return(rc);
9272 }
9273       
9274 char *lowercase(char *s)
9275 {
9276   char *p;
9277
9278   for (p = s; *p; p++)
9279     {
9280       if (isupper(*p))
9281         *p = tolower(*p);
9282     }
9283   return s;
9284 }
9285
9286 char *uppercase(char *s)
9287 {
9288   char *p;
9289
9290   for (p = s; *p; p++)
9291     {
9292       if (islower(*p))
9293         *p = toupper(*p);
9294     }
9295   return s;
9296 }
9297
9298 char *escape_string(char *s)
9299 {
9300   char *p, *q;
9301   char string[1024];
9302   char temp[1024];
9303   int i = 0;
9304   int spaces = 0;
9305
9306   if(ActiveDirectory) {
9307     return strdup(s);
9308   }
9309
9310   memset(string, '\0', sizeof(string));
9311
9312   q = s;
9313
9314   /* Escape any special characters */
9315
9316   for(; *q != '\0'; q++) {
9317     if(*q == ',')
9318       string[i++] = '\\';
9319     if(*q == '+') 
9320       string[i++] = '\\';
9321     if(*q == '"') 
9322       string[i++] = '\\';
9323     if(*q == '\\') 
9324       string[i++] = '\\';
9325     if(*q == '<') 
9326       string[i++] = '\\';
9327     if(*q == '>') 
9328       string[i++] = '\\';
9329     if(*q == ';')
9330       string[i++] = '\\';
9331     if(*q == '#')
9332       string[i++] = '\\';
9333     if(*q == '=')
9334       string[i++] = '\\';
9335
9336     string[i++] = *q;
9337   }
9338
9339   return strdup(string);
9340 }
9341
9342 int save_query_info(int argc, char **argv, void *hint)
9343 {
9344   int i;
9345   char **nargv = hint;
9346
9347   for(i = 0; i < argc; i++)
9348     nargv[i] = strdup(argv[i]);
9349
9350   return MR_CONT;
9351 }
9352
9353 int save_fsgroup_info(int argc, char **argv, void *hint)
9354 {
9355   int i;
9356   char **nargv = hint;
9357
9358   if(!fsgCount) 
9359     {
9360       for(i = 0; i < argc; i++)
9361         nargv[i] = strdup(argv[i]);
9362
9363       fsgCount++;
9364     }
9365
9366   return MR_CONT;
9367 }
9368
9369 int contains_member(LDAP *ldap_handle, char *dn_path, char *group_name, 
9370                     char *UserOu, char *user_name)
9371 {
9372   char         search_filter[1024];
9373   char         *attr_array[3];
9374   LK_ENTRY     *group_base;
9375   int          group_count;
9376   int          rc;
9377   char         temp[256];
9378
9379   if(ActiveDirectory)
9380     {
9381       sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
9382     }
9383   else
9384     {
9385       if(!strcmp(UserOu, user_ou))
9386         sprintf(temp, "uid=%s,%s,%s", user_name, UserOu, dn_path);
9387       else
9388         sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
9389     }
9390
9391   group_base = NULL;
9392   group_count = 0;
9393   
9394   sprintf(search_filter, "(&(objectClass=group)(cn=%s)(member=%s))",
9395           group_name, temp);
9396
9397   attr_array[0] = "mitMoiraId";
9398   attr_array[1] = NULL;
9399
9400   if ((rc = linklist_build(ldap_handle, dn_path, search_filter, 
9401                            attr_array, &group_base, &group_count,
9402                            LDAP_SCOPE_SUBTREE)) != 0)
9403     {
9404       com_err(whoami, 0, "Unable to check group %s for membership of %s : %s",
9405               group_name, user_name, ldap_err2string(rc));
9406       return(-1);
9407     }
9408           
9409   if (group_count)
9410     {
9411       rc = 1;
9412     }
9413   else 
9414     {
9415       rc = 0;
9416     }
9417
9418   linklist_free(group_base);
9419   group_count = 0;
9420   group_base = NULL;
9421
9422   return(rc);
9423 }
This page took 0.785875 seconds and 5 git commands to generate.