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