]> andersk Git - moira.git/blob - incremental/ldap/winad.c
092ddd786a463f518b0ffd194ab092983020555f
[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 (rc = mr_query("get_end_members_of_list", 1, av,
6355                     member_list_build, call_args))
6356     {
6357       if(rc == MR_LIST)
6358         return(0);
6359       
6360       com_err(whoami, 0, "Unable to populate list %s : %s", 
6361               group_name, error_message(rc));
6362       return(3);
6363     }
6364
6365   if (member_base != NULL)
6366     {
6367       ptr = member_base;
6368
6369       while(ptr != NULL)
6370         {
6371           if (!strcasecmp(ptr->type, "LIST"))
6372             {
6373               ptr = ptr->next;
6374               continue;
6375             }
6376
6377           if (!strcasecmp(ptr->type, "MACHINE") && !ProcessMachineContainer)
6378             {
6379               ptr = ptr->next;
6380               continue;
6381             }
6382
6383           if(!strcasecmp(ptr->type, "USER"))
6384             {
6385               if(!strcasecmp(ptr->member, PRODUCTION_PRINCIPAL) ||
6386                  !strcasecmp(ptr->member, TEST_PRINCIPAL))
6387                 {
6388                   ptr = ptr->next;
6389                   continue;
6390                 }
6391             }
6392
6393           ptr = ptr->next;
6394           group_members++;
6395         }
6396     }
6397
6398   if(max_group_members && !synchronize && (group_members > max_group_members))
6399     {
6400       com_err(whoami, 0, 
6401               "Group %s membership of %d exceeds maximum %d, skipping",
6402               group_name, group_members, max_group_members);
6403       return(0);
6404     }
6405
6406   members = (char **)malloc(sizeof(char *) * 2);
6407
6408   if (member_base != NULL)
6409     {
6410       ptr = member_base;
6411
6412       while (ptr != NULL)
6413         {
6414           if (!strcasecmp(ptr->type, "LIST"))
6415             {
6416               ptr = ptr->next;
6417               continue;
6418             }
6419           
6420           if (!strcasecmp(ptr->type, "MACHINE") && !ProcessMachineContainer)
6421             {
6422               ptr = ptr->next;
6423               continue;
6424             }
6425             
6426           if(!strcasecmp(ptr->type, "USER"))
6427             {
6428               if(!strcasecmp(ptr->member, PRODUCTION_PRINCIPAL) ||
6429                  !strcasecmp(ptr->member, TEST_PRINCIPAL))
6430                 {
6431                   ptr = ptr->next;
6432                   continue;
6433                 }
6434
6435               if ((rc = check_user(ldap_handle, dn_path, ptr->member,
6436                                    "")) == AD_NO_USER_FOUND)
6437                 {
6438                   com_err(whoami, 0, "creating user %s", ptr->member);
6439
6440                   av[0] = ptr->member;
6441                   call_args[0] = (char *)ldap_handle;
6442                   call_args[1] = dn_path;
6443                   call_args[2] = "";
6444                   call_args[3] = NULL;
6445                   callback_rc = 0;
6446                   
6447                   if (rc = mr_query("get_user_account_by_login", 1, av, 
6448                                     save_query_info, save_argv))
6449                     {
6450                       com_err(whoami, 0, "Unable to create user %s " 
6451                               "while populating group %s.", ptr->member,
6452                               group_name);
6453
6454                       return(3);
6455                     }
6456
6457                   if (rc = user_create(U_END, save_argv, call_args)) 
6458                     {
6459                       com_err(whoami, 0, "Unable to create user %s "
6460                               "while populating group %s.", ptr->member,
6461                               group_name);
6462                       
6463                       return(3);
6464                     }
6465           
6466                   if (callback_rc)
6467                     {
6468                       com_err(whoami, 0, "Unable to create user %s "
6469                               "while populating group %s", ptr->member, 
6470                               group_name);
6471
6472                       return(3);
6473                     }
6474                 }
6475
6476               pUserOu = user_ou;
6477                   
6478               if(ActiveDirectory) 
6479                 {
6480                   sprintf(member, "cn=%s,%s,%s", ptr->member, pUserOu, 
6481                           dn_path);
6482                 }
6483               else 
6484                 {
6485                   sprintf(member, "uid=%s,%s,%s", ptr->member, pUserOu, 
6486                           dn_path);
6487                 }
6488             }
6489           else if (!strcasecmp(ptr->type, "STRING"))
6490             {
6491               if (contact_create(ldap_handle, dn_path, ptr->member,
6492                                  contact_ou))
6493                 return(3);
6494
6495               pUserOu = contact_ou;
6496               sprintf(member, "cn=%s,%s,%s", escape_string(ptr->member), 
6497                       pUserOu, dn_path);
6498             }
6499           else if (!strcasecmp(ptr->type, "KERBEROS"))
6500             {
6501               if (contact_create(ldap_handle, dn_path, ptr->member, 
6502                                  kerberos_ou))
6503                 return(3);
6504
6505               pUserOu = kerberos_ou;
6506               sprintf(member, "cn=%s,%s,%s", escape_string(ptr->member), 
6507                       pUserOu, dn_path);
6508             }
6509           else if (!strcasecmp(ptr->type, "MACHINE"))
6510             {
6511               memset(machine_ou, '\0', sizeof(machine_ou));
6512               memset(NewMachineName, '\0', sizeof(NewMachineName));
6513
6514               if (!get_machine_ou(ldap_handle, dn_path, ptr->member,
6515                                  machine_ou, NewMachineName))
6516                 {
6517                   pUserOu = machine_ou;
6518                   sprintf(member, "cn=%s,%s,%s", NewMachineName, pUserOu,
6519                           dn_path);
6520                 }
6521               else
6522                 {
6523                   ptr = ptr->next;                  
6524                   continue;
6525                 }
6526             }
6527
6528           if(i > 1) 
6529             members = (char **)realloc(members, ((i + 2) * sizeof(char *)));
6530           members[i++] = strdup(member);
6531
6532           ptr = ptr->next;
6533         }
6534     
6535       linklist_free(member_base);
6536       member_base = NULL;
6537     }
6538
6539   members[i] = NULL;
6540
6541   sprintf(group_dn, "cn=%s,%s,%s", group_name, group_ou, dn_path);
6542
6543   if(GroupPopulateDelete)
6544     {
6545       n = 0;
6546       ADD_ATTR("member", member_v, LDAP_MOD_REPLACE);
6547       mods[n] = NULL;
6548       
6549       if ((rc = ldap_modify_s(ldap_handle, group_dn, 
6550                               mods)) != LDAP_SUCCESS)
6551         {
6552           com_err(whoami, 0,
6553                   "Unable to populate group membership for %s: %s",
6554                   group_dn, ldap_err2string(rc));
6555         }
6556   
6557       for (i = 0; i < n; i++)
6558         free(mods[i]);
6559     }
6560
6561   n = 0;
6562   ADD_ATTR("member", members, LDAP_MOD_REPLACE);
6563   mods[n] = NULL;
6564
6565   if ((rc = ldap_modify_s(ldap_handle, group_dn, 
6566                           mods)) != LDAP_SUCCESS)
6567     {
6568       com_err(whoami, 0,
6569               "Unable to populate group membership for %s: %s",
6570               group_dn, ldap_err2string(rc));
6571     }
6572   
6573   for (i = 0; i < n; i++)
6574     free(mods[i]);
6575     
6576   free(members);
6577
6578   return(0);
6579 }
6580
6581 int process_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
6582                   char *group_name, char *group_ou, char *group_membership, 
6583                   int group_security_flag, int type, char *maillist, 
6584                   char *nfsgroup)
6585 {
6586   char      before_desc[512];
6587   char      before_name[256];
6588   char      before_group_ou[256];
6589   char      before_group_membership[2];
6590   char      distinguishedName[256];
6591   char      ad_distinguishedName[256];
6592   char      filter[128];
6593   char      *attr_array[3];
6594   int       before_security_flag;
6595   int       group_count;
6596   int       rc;
6597   LK_ENTRY  *group_base;
6598   LK_ENTRY  *ptr;
6599   char      ou_both[512];
6600   char      ou_security[512];
6601   char      ou_distribution[512];
6602   char      ou_neither[512];
6603   char      group_dn[512];
6604
6605   memset(ad_distinguishedName, '\0', sizeof(ad_distinguishedName));
6606   sprintf(distinguishedName, "CN=%s,%s,%s", group_name, group_ou, dn_path);
6607
6608   memset(filter, '\0', sizeof(filter));
6609   group_base = NULL;
6610   group_count = 0;
6611
6612   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
6613                         "*", MoiraId, 
6614                         "samAccountName", &group_base, 
6615                         &group_count, filter))
6616     return(rc);
6617
6618   if (type == CHECK_GROUPS)
6619     {
6620       if (group_count == 1)
6621         {
6622           strcpy(group_dn, group_base->dn);
6623
6624           if (!strcasecmp(group_dn, distinguishedName))
6625             {
6626               linklist_free(group_base);
6627               return(0);
6628             }
6629         }
6630
6631       linklist_free(group_base);
6632
6633       if (group_count == 0)
6634         return(AD_NO_GROUPS_FOUND);
6635
6636       if (group_count == 1)
6637         return(AD_WRONG_GROUP_DN_FOUND);
6638
6639       return(AD_MULTIPLE_GROUPS_FOUND);
6640     }
6641
6642   if (group_count == 0)
6643     {
6644       return(AD_NO_GROUPS_FOUND);
6645     }
6646
6647   if (group_count > 1)
6648     {
6649       ptr = group_base;
6650
6651       strcpy(group_dn, ptr->dn);
6652
6653       while (ptr != NULL)
6654         {
6655           if (!strcasecmp(group_dn, ptr->value))
6656             break;
6657
6658           ptr = ptr->next;
6659         }
6660
6661       if (ptr == NULL)
6662         {
6663           com_err(whoami, 0, "%d groups with moira id = %s", group_count, 
6664                   MoiraId);
6665           ptr = group_base;
6666
6667           while (ptr != NULL)
6668             {
6669               com_err(whoami, 0, "%s with moira id = %s", ptr->value, MoiraId);
6670               ptr = ptr->next;
6671             }
6672
6673           linklist_free(group_base);
6674           return(AD_MULTIPLE_GROUPS_FOUND);
6675         }
6676
6677       ptr = group_base;
6678
6679       while (ptr != NULL)
6680         {
6681           strcpy(group_dn, ptr->dn);
6682
6683           if (strcasecmp(group_dn, ptr->value))
6684             rc = ldap_delete_s(ldap_handle, ptr->value);
6685
6686           ptr = ptr->next;
6687         }
6688
6689       linklist_free(group_base);
6690       memset(filter, '\0', sizeof(filter));
6691       group_base = NULL;
6692       group_count = 0;
6693
6694       if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
6695                             "*", MoiraId, 
6696                             "samAccountName", &group_base, 
6697                             &group_count, filter))
6698         return(rc);
6699
6700       if (group_count == 0)
6701         return(AD_NO_GROUPS_FOUND);
6702
6703       if (group_count > 1)
6704         return(AD_MULTIPLE_GROUPS_FOUND);
6705     }
6706
6707   strcpy(ad_distinguishedName, group_base->dn);
6708   linklist_free(group_base);
6709   group_base = NULL;
6710   group_count = 0;
6711
6712   attr_array[0] = "sAMAccountName";
6713   attr_array[1] = NULL;
6714   
6715   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6716                            &group_base, &group_count, 
6717                            LDAP_SCOPE_SUBTREE)) != 0)
6718     {
6719       com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6720               MoiraId, ldap_err2string(rc));
6721       return(rc);
6722     }
6723   
6724   sprintf(filter, "(sAMAccountName=%s)", group_base->value);
6725
6726   if (!strcasecmp(ad_distinguishedName, distinguishedName))
6727     {
6728       linklist_free(group_base);
6729       group_base = NULL;
6730       group_count = 0;
6731       return(0);
6732     }
6733
6734   linklist_free(group_base);
6735   group_base = NULL;
6736   group_count = 0;
6737   memset(ou_both, '\0', sizeof(ou_both));
6738   memset(ou_security, '\0', sizeof(ou_security));
6739   memset(ou_distribution, '\0', sizeof(ou_distribution));
6740   memset(ou_neither, '\0', sizeof(ou_neither));
6741   memset(before_name, '\0', sizeof(before_name));
6742   memset(before_desc, '\0', sizeof(before_desc));
6743   memset(before_group_membership, '\0', sizeof(before_group_membership));
6744   
6745   attr_array[0] = "name";
6746   attr_array[1] = NULL;
6747
6748   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6749                            &group_base, &group_count, 
6750                            LDAP_SCOPE_SUBTREE)) != 0)
6751     {
6752       com_err(whoami, 0, "Unable to get list name with MoiraId = %s: %s",
6753               MoiraId, ldap_err2string(rc));
6754       return(rc);
6755     }
6756
6757   strcpy(before_name, group_base->value);
6758   linklist_free(group_base);
6759   group_base = NULL;
6760   group_count = 0;
6761
6762   attr_array[0] = "description";
6763   attr_array[1] = NULL;
6764   
6765   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6766                            &group_base, &group_count, 
6767                            LDAP_SCOPE_SUBTREE)) != 0)
6768     {
6769       com_err(whoami, 0, 
6770               "Unable to get list description with MoiraId = %s: %s",
6771               MoiraId, ldap_err2string(rc));
6772       return(rc);
6773     }
6774
6775   if (group_count != 0)
6776     {
6777       strcpy(before_desc, group_base->value);
6778       linklist_free(group_base);
6779       group_base = NULL;
6780       group_count = 0;
6781     }
6782  
6783   change_to_lower_case(ad_distinguishedName);  
6784   strcpy(ou_both, group_ou_both);
6785   change_to_lower_case(ou_both);
6786   strcpy(ou_security, group_ou_security);
6787   change_to_lower_case(ou_security);
6788   strcpy(ou_distribution, group_ou_distribution);
6789   change_to_lower_case(ou_distribution);
6790   strcpy(ou_neither, group_ou_neither);
6791   change_to_lower_case(ou_neither);
6792
6793   if (strstr(ad_distinguishedName, ou_both))
6794     {
6795       strcpy(before_group_ou, group_ou_both);
6796       before_group_membership[0] = 'B';
6797       before_security_flag = 1;
6798     }
6799   else if (strstr(ad_distinguishedName, ou_security))
6800     {
6801       strcpy(before_group_ou, group_ou_security);
6802       before_group_membership[0] = 'S';
6803       before_security_flag = 1;
6804     }
6805   else if (strstr(ad_distinguishedName, ou_distribution))
6806     {
6807       strcpy(before_group_ou, group_ou_distribution);
6808       before_group_membership[0] = 'D';
6809       before_security_flag = 0;
6810     }
6811   else if (strstr(ad_distinguishedName, ou_neither))
6812     {
6813       strcpy(before_group_ou, group_ou_neither);
6814       before_group_membership[0] = 'N';
6815       before_security_flag = 0;
6816     }
6817   else
6818     return(AD_NO_OU_FOUND);
6819
6820   rc = group_rename(ldap_handle, dn_path, before_name, 
6821                     before_group_membership, 
6822                     before_group_ou, before_security_flag, before_desc,
6823                     group_name, group_membership, group_ou, 
6824                     group_security_flag,
6825                     before_desc, MoiraId, filter, maillist, nfsgroup);
6826
6827   return(rc);
6828 }
6829
6830 void change_to_lower_case(char *ptr)
6831 {
6832   int i;
6833
6834   for (i = 0; i < (int)strlen(ptr); i++)
6835     {
6836       ptr[i] = tolower(ptr[i]);
6837     }
6838 }
6839
6840 int ad_get_group(LDAP *ldap_handle, char *dn_path, 
6841                  char *group_name, char *group_membership, 
6842                  char *MoiraId, char *attribute,
6843                  LK_ENTRY **linklist_base, int *linklist_count,
6844                  char *rFilter)
6845 {
6846   LK_ENTRY  *pPtr;
6847   char  filter[128];
6848   char  *attr_array[3];
6849   char  *dn;
6850   int   rc;
6851
6852   (*linklist_base) = NULL;
6853   (*linklist_count) = 0;
6854
6855   if (strlen(rFilter) != 0)
6856     {
6857       strcpy(filter, rFilter);
6858       attr_array[0] = attribute;
6859       attr_array[1] = NULL;
6860       
6861       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6862                                linklist_base, linklist_count, 
6863                                LDAP_SCOPE_SUBTREE)) != 0)
6864         {
6865           com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6866                   MoiraId, ldap_err2string(rc));
6867          return(rc);
6868        }
6869
6870     if ((*linklist_count) == 1)
6871       {
6872         strcpy(rFilter, filter);
6873         return(0);
6874       }
6875     }
6876
6877   linklist_free((*linklist_base));
6878   (*linklist_base) = NULL;
6879   (*linklist_count) = 0;
6880
6881   if (strlen(MoiraId) != 0)
6882     {
6883       sprintf(filter, "(&(objectClass=group)(mitMoiraId=%s))", MoiraId);
6884
6885       attr_array[0] = attribute;
6886       attr_array[1] = NULL;
6887
6888       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6889                                linklist_base, linklist_count, 
6890                                LDAP_SCOPE_SUBTREE)) != 0)
6891         {
6892           com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6893                   MoiraId, ldap_err2string(rc));
6894          return(rc);
6895        }
6896     }
6897
6898   if ((*linklist_count) > 1)
6899     {
6900       com_err(whoami, 0, "multiple groups with mitMoiraId = %s", MoiraId);
6901       pPtr = (*linklist_base);
6902
6903       while (pPtr)
6904         {
6905           com_err(whoami, 0, "groups %s has mitMoiraId = %s", pPtr->value, 
6906                   MoiraId);
6907           pPtr = pPtr->next;
6908         }
6909
6910       linklist_free((*linklist_base));
6911       (*linklist_base) = NULL;
6912       (*linklist_count) = 0;
6913     }
6914
6915   if ((*linklist_count) == 1)
6916     {
6917
6918       pPtr = (*linklist_base);
6919       dn = strdup(pPtr->dn);
6920       dn += 3;
6921
6922       if (!memcmp(dn, group_name, strlen(group_name)))
6923         {
6924           strcpy(rFilter, filter);
6925           return(0);
6926         }
6927     }
6928
6929   linklist_free((*linklist_base));
6930   (*linklist_base) = NULL;
6931   (*linklist_count) = 0;
6932   sprintf(filter, "(sAMAccountName=%s%s)", group_name, group_suffix);
6933
6934   attr_array[0] = attribute;
6935   attr_array[1] = NULL;
6936
6937   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6938                            linklist_base, linklist_count, 
6939                            LDAP_SCOPE_SUBTREE)) != 0)
6940     {
6941       com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6942               MoiraId, ldap_err2string(rc));
6943       return(rc);
6944     }
6945
6946   if ((*linklist_count) == 1)
6947     {
6948       strcpy(rFilter, filter);
6949       return(0);
6950     }
6951
6952   return(0);
6953 }
6954
6955 int check_user(LDAP *ldap_handle, char *dn_path, char *UserName, char *MoiraId)
6956 {
6957   char filter[128];
6958   char *attr_array[3];
6959   char SamAccountName[64];
6960   int  group_count;
6961   int  rc;
6962   LK_ENTRY  *group_base;
6963   LK_ENTRY  *gPtr;
6964
6965   group_count = 0;
6966   group_base = NULL;
6967
6968   if (strlen(MoiraId) != 0)
6969     {
6970       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
6971
6972       attr_array[0] = "sAMAccountName";
6973       attr_array[1] = NULL;
6974       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6975                                &group_base, &group_count, 
6976                                LDAP_SCOPE_SUBTREE)) != 0)
6977         {
6978           com_err(whoami, 0, "Unable to process user %s : %s",
6979                   UserName, ldap_err2string(rc));
6980           return(rc);
6981         }
6982
6983       if (group_count > 1)
6984         {
6985           com_err(whoami, 0, "multiple users exist with MoiraId = %s",
6986                   MoiraId);
6987           gPtr = group_base;
6988
6989           while (gPtr)
6990             {
6991               com_err(whoami, 0, "user %s exist with MoiraId = %s",
6992                       gPtr->value, MoiraId);
6993               gPtr = gPtr->next;
6994             }
6995         }
6996     }
6997
6998   if (group_count != 1)
6999     {
7000       linklist_free(group_base);
7001       group_count = 0;
7002       group_base = NULL;
7003       sprintf(filter, "(sAMAccountName=%s)", UserName);
7004       attr_array[0] = "sAMAccountName";
7005       attr_array[1] = NULL;
7006
7007       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
7008                                &group_base, &group_count, 
7009                                LDAP_SCOPE_SUBTREE)) != 0)
7010         {
7011           com_err(whoami, 0, "Unable to process user %s : %s",
7012                   UserName, ldap_err2string(rc));
7013           return(rc);
7014         }
7015     }
7016
7017   if (group_count != 1)
7018     {
7019       linklist_free(group_base);
7020       return(AD_NO_USER_FOUND);
7021     }
7022
7023   strcpy(SamAccountName, group_base->value);
7024   linklist_free(group_base);
7025   group_count = 0;
7026   rc = 0;
7027
7028   if (strcmp(SamAccountName, UserName))
7029     {
7030       com_err(whoami, 0, 
7031               "User object %s with MoiraId %s has mismatched usernames " 
7032               "(LDAP username %s, Moira username %s)", SamAccountName,
7033               MoiraId, SamAccountName, UserName);
7034     }
7035
7036   return(0);
7037 }
7038
7039 void container_get_dn(char *src, char *dest)
7040 {
7041   char *sPtr;
7042   char *array[20];
7043   char name[256];
7044   int  n;
7045
7046   memset(array, '\0', 20 * sizeof(array[0]));
7047
7048   if (strlen(src) == 0)
7049     return;
7050
7051   strcpy(name, src);
7052   sPtr = name;
7053   n = 0;
7054   array[n] = name;
7055   ++n;
7056
7057   while (*sPtr)
7058     {
7059       if ((*sPtr) == '/')
7060         {
7061           (*sPtr) = '\0';
7062           ++sPtr;
7063           array[n] = sPtr;
7064           ++n;
7065         }
7066       else
7067         ++sPtr;
7068     }
7069
7070   strcpy(dest, "OU=");
7071
7072   while (n != 0)
7073     {
7074       strcat(dest, array[n-1]);
7075       --n;
7076       if (n > 0)
7077         {
7078           strcat(dest, ",OU=");
7079         }
7080     }
7081
7082   return;
7083 }
7084
7085 void container_get_name(char *src, char *dest)
7086 {
7087   char *sPtr;
7088   char *dPtr;
7089
7090   if (strlen(src) == 0)
7091     return;
7092
7093   sPtr = src;
7094   dPtr = src;
7095
7096   while (*sPtr)
7097     {
7098       if ((*sPtr) == '/')
7099         {
7100           dPtr = sPtr;
7101           ++dPtr;
7102         }
7103       ++sPtr;
7104     }
7105
7106   strcpy(dest, dPtr);
7107   return;
7108 }
7109
7110 void container_check(LDAP *ldap_handle, char *dn_path, char *name)
7111 {
7112   char cName[256];
7113   char *av[7];
7114   int  i;
7115   int  rc;
7116
7117   strcpy(cName, name);
7118
7119   for (i = 0; i < (int)strlen(cName); i++)
7120     {
7121       if (cName[i] == '/')
7122         {
7123           cName[i] = '\0';
7124           av[CONTAINER_NAME] = cName;
7125           av[CONTAINER_DESC] = "";
7126           av[CONTAINER_LOCATION] = "";
7127           av[CONTAINER_CONTACT] = "";
7128           av[CONTAINER_TYPE] = "";
7129           av[CONTAINER_ID] = "";
7130           av[CONTAINER_ROWID] = "";
7131           rc = container_create(ldap_handle, dn_path, 7, av);
7132
7133           if (rc == LDAP_SUCCESS)
7134             {
7135               com_err(whoami, 0, "container %s created without a mitMoiraId", 
7136                       cName);
7137             }
7138
7139           cName[i] = '/';
7140         }
7141     }
7142 }
7143
7144 int container_rename(LDAP *ldap_handle, char *dn_path, int beforec, 
7145                      char **before, int afterc, char **after)
7146 {
7147   char      dName[256];
7148   char      cName[256];
7149   char      new_cn[128];
7150   char      new_dn_path[256];
7151   char      temp[256];
7152   char      distinguishedName[256];
7153   char      *pPtr;
7154   int       rc;
7155   int       i;
7156
7157   memset(cName, '\0', sizeof(cName));
7158   container_get_name(after[CONTAINER_NAME], cName);
7159
7160   if (!check_container_name(cName))
7161     {
7162       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", 
7163               cName);
7164       return(AD_INVALID_NAME);
7165     }
7166
7167   memset(distinguishedName, '\0', sizeof(distinguishedName));
7168
7169   if (rc = container_get_distinguishedName(ldap_handle, dn_path, 
7170                                            distinguishedName, beforec, before))
7171     return(rc);
7172
7173   if (strlen(distinguishedName) == 0)
7174     {
7175       rc = container_create(ldap_handle, dn_path, afterc, after);
7176       return(rc);
7177     }
7178
7179   strcpy(temp, after[CONTAINER_NAME]);
7180   pPtr = temp;
7181
7182   for (i = 0; i < (int)strlen(temp); i++)
7183     {
7184       if (temp[i] == '/')
7185         {
7186           pPtr = &temp[i];
7187         }
7188     }
7189
7190   (*pPtr) = '\0';
7191
7192   container_get_dn(temp, dName);
7193
7194   if (strlen(temp) != 0)
7195     sprintf(new_dn_path, "%s,%s", dName, dn_path);
7196   else
7197     sprintf(new_dn_path, "%s", dn_path);
7198
7199   sprintf(new_cn, "OU=%s", cName);
7200
7201   container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
7202
7203   if ((rc = ldap_rename_s(ldap_handle, distinguishedName, new_cn, new_dn_path,
7204                           TRUE, NULL, NULL)) != LDAP_SUCCESS)
7205     {
7206       com_err(whoami, 0, "Unable to rename container from %s to %s : %s",
7207               before[CONTAINER_NAME], after[CONTAINER_NAME], 
7208               ldap_err2string(rc));
7209       return(rc);
7210     }
7211
7212   memset(dName, '\0', sizeof(dName));
7213   container_get_dn(after[CONTAINER_NAME], dName);
7214   rc = container_adupdate(ldap_handle, dn_path, dName, "", afterc, after);
7215
7216   return(rc);
7217 }
7218
7219 int container_delete(LDAP *ldap_handle, char *dn_path, int count, char **av)
7220 {
7221   char      distinguishedName[256];
7222   int       rc;
7223
7224   memset(distinguishedName, '\0', sizeof(distinguishedName));
7225
7226   if (rc = container_get_distinguishedName(ldap_handle, dn_path, 
7227                                            distinguishedName, count, av))
7228     return(rc);
7229
7230   if (strlen(distinguishedName) == 0)
7231     return(0);
7232
7233   if ((rc = ldap_delete_s(ldap_handle, distinguishedName)) != LDAP_SUCCESS)
7234     {
7235       if (rc == LDAP_NOT_ALLOWED_ON_NONLEAF)
7236         container_move_objects(ldap_handle, dn_path, distinguishedName);
7237       else
7238         com_err(whoami, 0, "Unable to delete container %s from directory : %s",
7239                 av[CONTAINER_NAME], ldap_err2string(rc));
7240     }
7241
7242   return(rc);
7243 }
7244
7245 int container_create(LDAP *ldap_handle, char *dn_path, int count, char **av)
7246 {
7247   char      *attr_array[3];
7248   LK_ENTRY  *group_base;
7249   int       group_count;
7250   LDAPMod   *mods[20];
7251   char      *objectClass_v[] = {"top", 
7252                            "organizationalUnit", 
7253                            NULL};
7254
7255   char *ou_v[] = {NULL, NULL};
7256   char *name_v[] = {NULL, NULL};
7257   char *moiraId_v[] = {NULL, NULL};
7258   char *desc_v[] = {NULL, NULL};
7259   char *managedBy_v[] = {NULL, NULL};
7260   char dName[256];
7261   char cName[256];
7262   char managedByDN[256];
7263   char filter[256];
7264   char temp[256];
7265   int  n;
7266   int  i;
7267   int  rc;
7268     
7269   memset(filter, '\0', sizeof(filter));
7270   memset(dName, '\0', sizeof(dName));
7271   memset(cName, '\0', sizeof(cName));
7272   memset(managedByDN, '\0', sizeof(managedByDN));
7273   container_get_dn(av[CONTAINER_NAME], dName);
7274   container_get_name(av[CONTAINER_NAME], cName);
7275
7276   if ((strlen(cName) == 0) || (strlen(dName) == 0))
7277     {
7278       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", 
7279               cName);
7280       return(AD_INVALID_NAME);
7281     }
7282
7283   if (!check_container_name(cName))
7284     {
7285       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", 
7286               cName);
7287       return(AD_INVALID_NAME);
7288     }
7289
7290   n = 0;
7291   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
7292   name_v[0] = cName;
7293   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
7294   ou_v[0] = cName;
7295   ADD_ATTR("ou", ou_v, LDAP_MOD_ADD);
7296
7297   if (strlen(av[CONTAINER_ROWID]) != 0)
7298     {
7299       moiraId_v[0] = av[CONTAINER_ROWID];
7300       ADD_ATTR("mitMoiraId", moiraId_v, LDAP_MOD_ADD);
7301     }
7302
7303   if (strlen(av[CONTAINER_DESC]) != 0)
7304     {
7305       desc_v[0] = av[CONTAINER_DESC];
7306       ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
7307     }
7308
7309   if ((strlen(av[CONTAINER_TYPE]) != 0) && (strlen(av[CONTAINER_ID]) != 0))
7310     {
7311       if (!strcasecmp(av[CONTAINER_TYPE], "KERBEROS"))
7312         {
7313           if (!contact_create(ldap_handle, dn_path, av[CONTAINER_ID], 
7314                               kerberos_ou))
7315             {
7316               sprintf(managedByDN, "CN=%s,%s,%s", av[CONTAINER_ID], 
7317                       kerberos_ou, dn_path);
7318               managedBy_v[0] = managedByDN;
7319               ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_ADD);
7320             }
7321         }
7322       else
7323         {
7324           if (!strcasecmp(av[CONTAINER_TYPE], "USER"))
7325             {
7326               sprintf(filter, "(&(cn=%s)(&(objectCategory=person)"
7327                       "(objectClass=user)))", av[CONTAINER_ID]);
7328             }
7329
7330           if (!strcasecmp(av[CONTAINER_TYPE], "LIST"))
7331             {
7332               sprintf(filter, "(&(objectClass=group)(cn=%s))", 
7333                       av[CONTAINER_ID]);
7334             }
7335
7336           if (strlen(filter) != 0)
7337             {
7338               attr_array[0] = "distinguishedName";
7339               attr_array[1] = NULL;
7340               group_count = 0;
7341               group_base = NULL;
7342               if ((rc = linklist_build(ldap_handle, dn_path, filter, 
7343                                        attr_array, 
7344                                        &group_base, &group_count, 
7345                                        LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7346                 {
7347                   if (group_count == 1)
7348                     {
7349                       strcpy(managedByDN, group_base->value);
7350                       managedBy_v[0] = managedByDN;
7351                       ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_ADD);
7352                     }
7353                   linklist_free(group_base);
7354                   group_base = NULL;
7355                   group_count = 0;
7356                 }
7357             }
7358         }
7359     }
7360   
7361   mods[n] = NULL;
7362
7363   sprintf(temp, "%s,%s", dName, dn_path);
7364   rc = ldap_add_ext_s(ldap_handle, temp, mods, NULL, NULL);
7365   
7366   for (i = 0; i < n; i++)
7367     free(mods[i]);
7368   
7369   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
7370     {
7371       com_err(whoami, 0, "Unable to create container %s : %s",
7372               cName, ldap_err2string(rc));
7373       return(rc);
7374     }
7375
7376   if (rc == LDAP_ALREADY_EXISTS)
7377     {
7378       if (strlen(av[CONTAINER_ROWID]) != 0)
7379         rc = container_adupdate(ldap_handle, dn_path, dName, "", count, av);
7380     }
7381
7382   return(rc);
7383 }
7384
7385 int container_update(LDAP *ldap_handle, char *dn_path, int beforec, 
7386                      char **before, int afterc, char **after)
7387 {
7388   char distinguishedName[256];
7389   int  rc;
7390
7391   memset(distinguishedName, '\0', sizeof(distinguishedName));
7392
7393   if (rc = container_get_distinguishedName(ldap_handle, dn_path, 
7394                                            distinguishedName, afterc, after))
7395     return(rc);
7396
7397   if (strlen(distinguishedName) == 0)
7398     {
7399       rc = container_create(ldap_handle, dn_path, afterc, after);
7400       return(rc);
7401     }
7402   
7403   container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
7404   rc = container_adupdate(ldap_handle, dn_path, "", distinguishedName, afterc,
7405                           after);
7406
7407   return(rc);
7408 }
7409
7410 int container_get_distinguishedName(LDAP *ldap_handle, char *dn_path, 
7411                                     char *distinguishedName, int count, 
7412                                     char **av)
7413 {
7414   char      *attr_array[3];
7415   LK_ENTRY  *group_base;
7416   int       group_count;
7417   char      dName[256];
7418   char      cName[256];
7419   char      filter[512];
7420   int       rc;
7421
7422   memset(filter, '\0', sizeof(filter));
7423   memset(dName, '\0', sizeof(dName));
7424   memset(cName, '\0', sizeof(cName));
7425   container_get_dn(av[CONTAINER_NAME], dName);
7426   container_get_name(av[CONTAINER_NAME], cName);
7427
7428   if (strlen(dName) == 0)
7429     {
7430       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", 
7431               av[CONTAINER_NAME]);
7432       return(AD_INVALID_NAME);
7433     }
7434
7435   if (!check_container_name(cName))
7436     {
7437       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", 
7438               cName);
7439       return(AD_INVALID_NAME);
7440     }
7441   
7442   sprintf(filter, "(&(objectClass=organizationalUnit)(mitMoiraId=%s))", 
7443           av[CONTAINER_ROWID]);
7444   attr_array[0] = "distinguishedName";
7445   attr_array[1] = NULL;
7446   group_count = 0;
7447   group_base = NULL;
7448
7449   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
7450                            &group_base, &group_count, 
7451                            LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7452     {
7453       if (group_count == 1)
7454         {
7455           strcpy(distinguishedName, group_base->value);
7456         }
7457
7458       linklist_free(group_base);
7459       group_base = NULL;
7460       group_count = 0;
7461     }
7462
7463   if (strlen(distinguishedName) == 0)
7464     {
7465       sprintf(filter, "(&(objectClass=organizationalUnit)"
7466               "(distinguishedName=%s,%s))", dName, dn_path);
7467       attr_array[0] = "distinguishedName";
7468       attr_array[1] = NULL;
7469       group_count = 0;
7470       group_base = NULL;
7471
7472       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
7473                                &group_base, &group_count, 
7474                                LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7475         {
7476           if (group_count == 1)
7477             {
7478               strcpy(distinguishedName, group_base->value);
7479             }
7480
7481           linklist_free(group_base);
7482           group_base = NULL;
7483           group_count = 0;
7484         }
7485     }
7486
7487   return(0);
7488 }
7489
7490 int container_adupdate(LDAP *ldap_handle, char *dn_path, char *dName, 
7491                        char *distinguishedName, int count, char **av)
7492 {
7493   char      *attr_array[5];
7494   LK_ENTRY  *group_base;
7495   LK_ENTRY  *pPtr;
7496   LDAPMod   *mods[20];
7497   int       group_count;
7498   char      filter[512];
7499   char      *moiraId_v[] = {NULL, NULL};
7500   char      *desc_v[] = {NULL, NULL};
7501   char      *managedBy_v[] = {NULL, NULL};
7502   char      managedByDN[256];
7503   char      moiraId[64];
7504   char      desc[256];
7505   char      ad_path[512];
7506   int       rc;
7507   int       i;
7508   int       n;
7509
7510
7511   strcpy(ad_path, distinguishedName);
7512
7513   if (strlen(dName) != 0)
7514     sprintf(ad_path, "%s,%s", dName, dn_path);
7515
7516   sprintf(filter, "(&(objectClass=organizationalUnit)(distinguishedName=%s))",
7517           ad_path);
7518
7519   if (strlen(av[CONTAINER_ID]) != 0)
7520     sprintf(filter, "(&(objectClass=organizationalUnit)(mitMoiraId=%s))", 
7521             av[CONTAINER_ROWID]);
7522
7523   attr_array[0] = "mitMoiraId";
7524   attr_array[1] = "description";
7525   attr_array[2] = "managedBy";
7526   attr_array[3] = NULL;
7527   group_count = 0;
7528   group_base = NULL;
7529
7530   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
7531                            &group_base, &group_count, 
7532                            LDAP_SCOPE_SUBTREE)) != LDAP_SUCCESS)
7533     {
7534       com_err(whoami, 0, "Unable to retreive container info for %s : %s",
7535               av[CONTAINER_NAME], ldap_err2string(rc));
7536       return(rc);
7537     }
7538
7539   memset(managedByDN, '\0', sizeof(managedByDN));
7540   memset(moiraId, '\0', sizeof(moiraId));
7541   memset(desc, '\0', sizeof(desc));
7542   pPtr = group_base;
7543
7544   while (pPtr)
7545     {
7546       if (!strcasecmp(pPtr->attribute, "description"))
7547         strcpy(desc, pPtr->value);
7548       else if (!strcasecmp(pPtr->attribute, "managedBy"))
7549         strcpy(managedByDN, pPtr->value);
7550       else if (!strcasecmp(pPtr->attribute, "mitMoiraId"))
7551         strcpy(moiraId, pPtr->value);
7552       pPtr = pPtr->next;
7553     }
7554
7555   linklist_free(group_base);
7556   group_base = NULL;
7557   group_count = 0;
7558
7559   n = 0;
7560   if (strlen(av[CONTAINER_ROWID]) != 0)
7561     {
7562       moiraId_v[0] = av[CONTAINER_ROWID];
7563       ADD_ATTR("mitMoiraId", moiraId_v, LDAP_MOD_REPLACE);
7564     }
7565
7566   if (strlen(av[CONTAINER_DESC]) != 0)
7567     {
7568       attribute_update(ldap_handle, ad_path, av[CONTAINER_DESC], "description",
7569                        dName);
7570     }
7571   else
7572     {
7573       if (strlen(desc) != 0)
7574         {
7575           attribute_update(ldap_handle, ad_path, "", "description", dName);
7576         }
7577     }
7578
7579   if ((strlen(av[CONTAINER_TYPE]) != 0) && (strlen(av[CONTAINER_ID]) != 0))
7580     {
7581       if (!strcasecmp(av[CONTAINER_TYPE], "KERBEROS"))
7582         {
7583           if (!contact_create(ldap_handle, dn_path, av[CONTAINER_ID], 
7584                               kerberos_ou))
7585             {
7586               sprintf(managedByDN, "CN=%s,%s,%s", av[CONTAINER_ID], 
7587                       kerberos_ou, dn_path);
7588               managedBy_v[0] = managedByDN;
7589               ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_REPLACE);
7590             }
7591           else
7592             {
7593               if (strlen(managedByDN) != 0)
7594                 {
7595                   attribute_update(ldap_handle, ad_path, "", "managedBy", 
7596                                    dName);
7597                 }
7598             }
7599         }
7600       else
7601         {
7602           memset(filter, '\0', sizeof(filter));
7603
7604           if (!strcasecmp(av[CONTAINER_TYPE], "USER"))
7605             {
7606               sprintf(filter, "(&(cn=%s)(&(objectCategory=person)"
7607                       "(objectClass=user)))", av[CONTAINER_ID]);
7608             }
7609
7610           if (!strcasecmp(av[CONTAINER_TYPE], "LIST"))
7611             {
7612               sprintf(filter, "(&(objectClass=group)(cn=%s))", 
7613                       av[CONTAINER_ID]);
7614             }
7615
7616           if (strlen(filter) != 0)
7617             {
7618               attr_array[0] = "distinguishedName";
7619               attr_array[1] = NULL;
7620               group_count = 0;
7621               group_base = NULL;
7622               if ((rc = linklist_build(ldap_handle, dn_path, filter, 
7623                                        attr_array, &group_base, &group_count, 
7624                                        LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7625                 {
7626                   if (group_count == 1)
7627                     {
7628                       strcpy(managedByDN, group_base->value);
7629                       managedBy_v[0] = managedByDN;
7630                       ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_REPLACE);
7631                     }
7632                   else
7633                     {
7634                       if (strlen(managedByDN) != 0)
7635                         {
7636                           attribute_update(ldap_handle, ad_path, "", 
7637                                            "managedBy", dName);
7638                         }
7639                     }
7640
7641                   linklist_free(group_base);
7642                   group_base = NULL;
7643                   group_count = 0;
7644                 }
7645             }
7646           else
7647             {
7648               if (strlen(managedByDN) != 0)
7649                 {
7650                   attribute_update(ldap_handle, ad_path, "", "managedBy", 
7651                                    dName);
7652                 }
7653             }
7654         }
7655     }
7656
7657   mods[n] = NULL;
7658
7659   if (n == 0)
7660     return(LDAP_SUCCESS);
7661
7662   rc = ldap_modify_s(ldap_handle, ad_path, mods);
7663
7664   for (i = 0; i < n; i++)
7665     free(mods[i]);
7666
7667   if (rc != LDAP_SUCCESS)
7668     {
7669       com_err(whoami, 0, "Unable to modify container info for %s : %s",
7670               av[CONTAINER_NAME], ldap_err2string(rc));
7671       return(rc);
7672     }
7673   
7674   return(rc);
7675 }
7676
7677 int container_move_objects(LDAP *ldap_handle, char *dn_path, char *dName)
7678 {
7679   char      *attr_array[3];
7680   LK_ENTRY  *group_base;
7681   LK_ENTRY  *pPtr;
7682   int       group_count;
7683   char      filter[512];
7684   char      new_cn[128];
7685   char      temp[256];
7686   int       rc;
7687   int       NumberOfEntries = 10;
7688   int       i;
7689   int       count;
7690
7691   rc = ldap_set_option(ldap_handle, LDAP_OPT_SIZELIMIT, &NumberOfEntries);
7692
7693   for (i = 0; i < 3; i++)
7694     {
7695       memset(filter, '\0', sizeof(filter));
7696
7697       if (i == 0)
7698         {
7699           strcpy(filter, "(!(|(objectClass=computer)"
7700                  "(objectClass=organizationalUnit)))");
7701           attr_array[0] = "cn";
7702           attr_array[1] = NULL;
7703         }
7704       else if (i == 1)
7705         {
7706           strcpy(filter, "(objectClass=computer)");
7707           attr_array[0] = "cn";
7708           attr_array[1] = NULL;
7709         }
7710       else
7711         {
7712           strcpy(filter, "(objectClass=organizationalUnit)");
7713           attr_array[0] = "ou";
7714           attr_array[1] = NULL;
7715         }
7716
7717       while (1)
7718         {
7719           if ((rc = linklist_build(ldap_handle, dName, filter, attr_array, 
7720                                    &group_base, &group_count, 
7721                                    LDAP_SCOPE_SUBTREE)) != LDAP_SUCCESS)
7722             {
7723               break;
7724             }
7725
7726           if (group_count == 0)
7727             break;
7728
7729           pPtr = group_base;
7730
7731           while(pPtr)
7732             {
7733               if (!strcasecmp(pPtr->attribute, "cn"))
7734                 {
7735                   sprintf(new_cn, "cn=%s", pPtr->value);
7736                   if (i == 0)
7737                     sprintf(temp, "%s,%s", orphans_other_ou, dn_path);
7738                   if (i == 1)
7739                     sprintf(temp, "%s,%s", orphans_machines_ou, dn_path);
7740                   count = 1;
7741
7742                   while (1)
7743                     {
7744                       rc = ldap_rename_s(ldap_handle, pPtr->dn, new_cn, temp,
7745                                          TRUE, NULL, NULL);
7746                       if (rc == LDAP_ALREADY_EXISTS)
7747                         {
7748                           sprintf(new_cn, "cn=%s_%d", pPtr->value, count);
7749                           ++count;
7750                         }
7751                       else
7752                         break;
7753                     }
7754                 }
7755               else if (!strcasecmp(pPtr->attribute, "ou"))
7756                 {
7757                   rc = ldap_delete_s(ldap_handle, pPtr->dn);
7758                 }
7759
7760               pPtr = pPtr->next;
7761             }
7762
7763           linklist_free(group_base);
7764           group_base = NULL;
7765           group_count = 0;
7766         }
7767     }
7768
7769   return(0);
7770 }
7771
7772 int get_machine_ou(LDAP *ldap_handle, char *dn_path, char *member, 
7773                    char *machine_ou, char *NewMachineName)
7774 {
7775   LK_ENTRY  *group_base;
7776   int  group_count;
7777   int  i;
7778   char filter[128];
7779   char *attr_array[3];
7780   char cn[256];
7781   char dn[256];
7782   char temp[256];
7783   char *pPtr;
7784   int   rc;
7785
7786   strcpy(NewMachineName, member);
7787   rc = moira_connect();
7788   rc = GetMachineName(NewMachineName);
7789   moira_disconnect();
7790
7791   if (strlen(NewMachineName) == 0)
7792     {
7793       com_err(whoami, 0, "Unable to find alais for machine %s in Moira", 
7794               member);
7795       return(1);
7796     }
7797
7798   pPtr = NULL;
7799   pPtr = strchr(NewMachineName, '.');
7800
7801   if (pPtr != NULL)
7802     (*pPtr) = '\0';
7803
7804   group_base = NULL;
7805   group_count = 0;
7806   sprintf(filter, "(sAMAccountName=%s$)", NewMachineName);
7807   attr_array[0] = "cn";
7808   attr_array[1] = NULL;
7809   sprintf(temp, "%s", dn_path);
7810
7811   if ((rc = linklist_build(ldap_handle, temp, filter, attr_array, 
7812                            &group_base, &group_count, 
7813                            LDAP_SCOPE_SUBTREE)) != 0)
7814     {
7815       com_err(whoami, 0, "Unable to process machine %s : %s",
7816               member, ldap_err2string(rc));
7817       return(1);
7818     }
7819
7820   if (group_count != 1)
7821     {
7822       return(1);
7823     }
7824
7825   strcpy(dn, group_base->dn);
7826   strcpy(cn, group_base->value);
7827
7828   for (i = 0; i < (int)strlen(dn); i++)
7829     dn[i] = tolower(dn[i]);
7830
7831   for (i = 0; i < (int)strlen(cn); i++)
7832     cn[i] = tolower(cn[i]);
7833
7834   linklist_free(group_base);
7835   pPtr = NULL;
7836   pPtr = strstr(dn, cn);
7837
7838   if (pPtr == NULL)
7839     {
7840       com_err(whoami, 0, "Unable to process machine %s",
7841               member);
7842       return(1);
7843     }
7844
7845   pPtr += strlen(cn) + 1;
7846   strcpy(machine_ou, pPtr);
7847   pPtr = NULL;
7848   pPtr = strstr(machine_ou, "dc=");
7849
7850   if (pPtr == NULL)
7851     {
7852       com_err(whoami, 0, "Unable to process machine %s",
7853               member);
7854       return(1);
7855     }
7856
7857   --pPtr;
7858   (*pPtr) = '\0';
7859
7860   return(0);
7861 }
7862
7863 int machine_move_to_ou(LDAP *ldap_handle, char * dn_path, 
7864                        char *MoiraMachineName, char *DestinationOu)
7865 {
7866   char        NewCn[128];
7867   char        OldDn[512];
7868   char        MachineName[128];
7869   char        filter[128];
7870   char        *attr_array[3];
7871   char        NewOu[256];
7872   char        *cPtr = NULL;
7873   int         group_count;
7874   long        rc;
7875   LK_ENTRY    *group_base;
7876
7877   group_count = 0;
7878   group_base = NULL;
7879   
7880   strcpy(MachineName, MoiraMachineName);
7881   rc = GetMachineName(MachineName);
7882
7883   if (strlen(MachineName) == 0)
7884     {
7885       com_err(whoami, 0, "Unable to find alais for machine %s in Moira", 
7886               MoiraMachineName);
7887       return(1);
7888     }
7889   
7890   cPtr = strchr(MachineName, '.');
7891
7892   if (cPtr != NULL)
7893     (*cPtr) = '\0';
7894
7895   sprintf(filter, "(sAMAccountName=%s$)", MachineName);
7896   attr_array[0] = "sAMAccountName";
7897   attr_array[1] = NULL;
7898
7899   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
7900                            &group_base, 
7901                            &group_count, LDAP_SCOPE_SUBTREE)) != 0)
7902     {
7903       com_err(whoami, 0, "Unable to process machine %s : %s",
7904               MoiraMachineName, ldap_err2string(rc));
7905       return(1);
7906     }
7907   
7908   if (group_count == 1)
7909     strcpy(OldDn, group_base->dn);
7910
7911   linklist_free(group_base);
7912   group_base = NULL;
7913
7914   if (group_count != 1)
7915     {
7916       com_err(whoami, 0, "Unable to find machine %s in directory: %s", 
7917               MoiraMachineName);
7918       return(1);
7919     }
7920
7921   sprintf(NewOu, "%s,%s", DestinationOu, dn_path);
7922   cPtr = strchr(OldDn, ',');
7923
7924   if (cPtr != NULL)
7925     {
7926       ++cPtr;
7927       if (!strcasecmp(cPtr, NewOu))
7928         return(0);
7929     }
7930
7931   sprintf(NewCn, "CN=%s", MachineName);
7932   rc = ldap_rename_s(ldap_handle, OldDn, NewCn, NewOu, TRUE, NULL, NULL);
7933
7934   return(rc);
7935 }
7936
7937 int machine_check(LDAP *ldap_handle, char *dn_path, char *machine_name)
7938 {
7939   char    Name[128];
7940   char    *pPtr;
7941   int     rc;
7942   
7943   memset(Name, '\0', sizeof(Name));
7944   strcpy(Name, machine_name);
7945   pPtr = NULL;
7946   pPtr = strchr(Name, '.');
7947
7948   if (pPtr != NULL)
7949     (*pPtr) = '\0';
7950
7951   strcat(Name, "$");
7952   return(!(rc = checkADname(ldap_handle, dn_path, Name)));
7953 }
7954
7955 int machine_get_moira_container(LDAP *ldap_handle, char *dn_path, 
7956                                 char *machine_name, char *container_name)
7957 {
7958   int     rc;
7959   char    *av[2];
7960   char    *call_args[2];
7961   
7962   av[0] = machine_name;
7963   call_args[0] = (char *)container_name;
7964   rc = mr_query("get_machine_to_container_map", 1, av, 
7965                 machine_GetMoiraContainer, call_args);
7966   return(rc);
7967 }
7968
7969 int machine_GetMoiraContainer(int ac, char **av, void *ptr)
7970 {
7971   char **call_args;
7972   
7973   call_args = ptr;
7974   strcpy(call_args[0], av[1]);
7975   return(0);
7976 }
7977
7978 int Moira_container_group_create(char **after)
7979 {
7980   long rc;
7981   char GroupName[64];
7982   char *argv[20];
7983   
7984   memset(GroupName, '\0', sizeof(GroupName));
7985   rc = Moira_groupname_create(GroupName, after[CONTAINER_NAME], 
7986                               after[CONTAINER_ROWID]);
7987   if (rc)
7988     return rc;
7989   
7990   argv[L_NAME] = GroupName;
7991   argv[L_ACTIVE] = "1";
7992   argv[L_PUBLIC] = "0";
7993   argv[L_HIDDEN] = "0";
7994   argv[L_MAILLIST] = "0";
7995   argv[L_GROUP] = "1";
7996   argv[L_GID] = UNIQUE_GID;
7997   argv[L_NFSGROUP] = "0";
7998   argv[L_MAILMAN] = "0";
7999   argv[L_MAILMAN_SERVER] = "[NONE]";
8000   argv[L_DESC] = "auto created container group";
8001   argv[L_ACE_TYPE] = "USER";
8002   argv[L_MEMACE_TYPE] = "USER";
8003   argv[L_ACE_NAME] = "sms";
8004   argv[L_MEMACE_NAME] = "sms";
8005
8006   if (rc = mr_query("add_list", 15, argv, NULL, NULL))
8007     {
8008       com_err(whoami, 0, 
8009               "Unable to create container group %s for container %s: %s",
8010               GroupName, after[CONTAINER_NAME], error_message(rc));
8011     }
8012
8013   Moira_setContainerGroup(after[CONTAINER_NAME], GroupName);
8014   Moira_addGroupToParent(after[CONTAINER_NAME], GroupName);
8015   
8016   return(rc);
8017 }
8018
8019 int Moira_container_group_update(char **before, char **after)
8020 {
8021   long rc;
8022   char BeforeGroupName[64];
8023   char AfterGroupName[64];
8024   char *argv[20];
8025   
8026   if (!strcasecmp(after[CONTAINER_NAME], before[CONTAINER_NAME]))
8027     return(0);
8028
8029   memset(BeforeGroupName, '\0', sizeof(BeforeGroupName));
8030   Moira_getGroupName(after[CONTAINER_NAME], BeforeGroupName, 0);
8031   if (strlen(BeforeGroupName) == 0)
8032     return(0);
8033
8034   memset(AfterGroupName, '\0', sizeof(AfterGroupName));
8035   rc = Moira_groupname_create(AfterGroupName, after[CONTAINER_NAME], 
8036                               after[CONTAINER_ROWID]);
8037   if (rc)
8038     return rc;
8039
8040   if (strcasecmp(BeforeGroupName, AfterGroupName))
8041     {
8042       argv[L_NAME] = BeforeGroupName;
8043       argv[L_NAME + 1] = AfterGroupName;
8044       argv[L_ACTIVE + 1] = "1";
8045       argv[L_PUBLIC + 1] = "0";
8046       argv[L_HIDDEN + 1] = "0";
8047       argv[L_MAILLIST + 1] = "0";
8048       argv[L_GROUP + 1] = "1";
8049       argv[L_GID + 1] = UNIQUE_GID;
8050       argv[L_NFSGROUP + 1] = "0";
8051       argv[L_MAILMAN + 1] = "0";
8052       argv[L_MAILMAN_SERVER + 1] = "[NONE]";
8053       argv[L_DESC + 1] = "auto created container group";
8054       argv[L_ACE_TYPE + 1] = "USER";
8055       argv[L_MEMACE_TYPE + 1] = "USER";
8056       argv[L_ACE_NAME + 1] = "sms";
8057       argv[L_MEMACE_NAME + 1] = "sms";
8058       
8059       if (rc = mr_query("update_list", 16, argv, NULL, NULL))
8060         {
8061           com_err(whoami, 0, 
8062                   "Unable to rename container group from %s to %s: %s",
8063                   BeforeGroupName, AfterGroupName, error_message(rc));
8064         }
8065     }
8066   
8067   return(rc);
8068 }
8069
8070 int Moira_container_group_delete(char **before)
8071 {
8072   long rc = 0;
8073   char *argv[13];
8074   char GroupName[64];
8075   char ParentGroupName[64];
8076   
8077   memset(ParentGroupName, '\0', sizeof(ParentGroupName));
8078   Moira_getGroupName(before[CONTAINER_NAME], ParentGroupName, 1);
8079
8080   memset(GroupName, '\0', sizeof(GroupName));
8081
8082   if (strcmp(before[CONTAINER_GROUP_NAME], "[none]"))
8083     strcpy(GroupName, before[CONTAINER_GROUP_NAME]);
8084   
8085   if ((strlen(ParentGroupName) != 0) && (strlen(GroupName) != 0))
8086     {
8087       argv[0] = ParentGroupName;
8088       argv[1] = "LIST";
8089       argv[2] = GroupName;
8090
8091       if (rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL))
8092         {
8093           com_err(whoami, 0, 
8094                   "Unable to delete container group %s from list: %s",
8095                   GroupName, ParentGroupName, error_message(rc));
8096         }
8097     }
8098   
8099   if (strlen(GroupName) != 0)
8100     {
8101       argv[0] = GroupName;
8102
8103       if (rc = mr_query("delete_list", 1, argv, NULL, NULL))
8104         {
8105           com_err(whoami, 0, "Unable to delete container group %s : %s",
8106                   GroupName, error_message(rc));
8107         }
8108     }
8109   
8110   return(rc);
8111 }
8112
8113 int Moira_groupname_create(char *GroupName, char *ContainerName,
8114                            char *ContainerRowID)
8115 {
8116   char *ptr;
8117   char *ptr1;
8118   char temp[64];
8119   char newGroupName[64];
8120   char tempGroupName[64];
8121   char tempgname[64];
8122   char *argv[1];
8123   int  i;
8124   long rc;
8125
8126   strcpy(temp, ContainerName);
8127   
8128   ptr1 = strrchr(temp, '/');
8129
8130   if (ptr1 != NULL)
8131   {
8132     *ptr1 = '\0';
8133     ptr = ++ptr1;
8134     ptr1 = strrchr(temp, '/');
8135
8136     if (ptr1 != NULL)
8137     {
8138         sprintf(tempgname, "%s-%s", ++ptr1, ptr);
8139     }
8140     else
8141         strcpy(tempgname, ptr);
8142   }
8143   else
8144     strcpy(tempgname, temp);
8145
8146   if (strlen(tempgname) > 25)
8147     tempgname[25] ='\0';
8148
8149   sprintf(newGroupName, "cnt-%s", tempgname);
8150
8151   /* change everything to lower case */
8152   ptr = newGroupName;
8153
8154   while (*ptr)
8155     {
8156       if (isupper(*ptr))
8157         *ptr = tolower(*ptr);
8158
8159       if (*ptr == ' ')
8160         *ptr = '-';
8161
8162       ptr++;
8163     }
8164
8165   strcpy(tempGroupName, newGroupName);
8166   i = (int)'0';
8167
8168   /* append 0-9 then a-z if a duplicate is found */
8169   while(1)
8170     {
8171       argv[0] = newGroupName;
8172
8173       if (rc = mr_query("get_list_info", 1, argv, NULL, NULL))
8174         {
8175           if (rc == MR_NO_MATCH)
8176             break;
8177           com_err(whoami, 0, "Moira error while creating group name for "
8178                   "container %s : %s", ContainerName, error_message(rc));
8179           return rc;
8180         }
8181
8182       sprintf(newGroupName, "%s-%c", tempGroupName, i);
8183
8184       if (i == (int)'z')
8185         {
8186           com_err(whoami, 0, "Unable to find a unique group name for "
8187                   "container %s: too many duplicate container names",
8188                   ContainerName);
8189           return 1;
8190         }
8191
8192       if (i == '9')
8193         i = 'a';
8194       else
8195         i++;
8196     }
8197
8198   strcpy(GroupName, newGroupName);
8199   return(0);
8200 }
8201
8202 int Moira_setContainerGroup(char *origContainerName, char *GroupName)
8203 {
8204   long rc;
8205   char *argv[3];
8206   
8207   argv[0] = origContainerName;
8208   argv[1] = GroupName;
8209   
8210   if ((rc = mr_query("set_container_list", 2, argv, NULL, NULL)))
8211     {
8212       com_err(whoami, 0, 
8213               "Unable to set container group %s in container %s: %s",
8214               GroupName, origContainerName, error_message(rc));
8215     }
8216   
8217   return(0);
8218 }
8219
8220 int Moira_addGroupToParent(char *origContainerName, char *GroupName)
8221  {
8222    char ContainerName[64];
8223    char ParentGroupName[64];
8224    char *argv[3];
8225    long rc;
8226
8227    strcpy(ContainerName, origContainerName);
8228    
8229    Moira_getGroupName(ContainerName, ParentGroupName, 1);
8230
8231    /* top-level container */
8232    if (strlen(ParentGroupName) == 0)
8233      return(0);
8234    
8235    argv[0] = ParentGroupName;
8236    argv[1] = "LIST";
8237    argv[2] = GroupName;
8238
8239    if ((rc = mr_query("add_member_to_list", 3, argv, NULL, NULL)))
8240      {
8241        com_err(whoami, 0, 
8242                "Unable to add container group %s to parent group %s: %s",
8243                GroupName, ParentGroupName, error_message(rc));
8244      }
8245    
8246    return(0);
8247  }
8248
8249 int Moira_getContainerGroup(int ac, char **av, void *ptr)
8250 {
8251   char **call_args;
8252   
8253   call_args = ptr;
8254   strcpy(call_args[0], av[1]);
8255
8256   return(0);
8257 }
8258
8259 int Moira_getGroupName(char *origContainerName, char *GroupName,
8260                        int ParentFlag)
8261 {
8262   char ContainerName[64];
8263   char *argv[3];
8264   char *call_args[3];
8265   char *ptr;
8266   long rc;
8267
8268   strcpy(ContainerName, origContainerName);
8269
8270   if (ParentFlag)
8271     {
8272       ptr = strrchr(ContainerName, '/');
8273
8274       if (ptr != NULL)
8275         (*ptr) = '\0';
8276       else
8277         return(0);
8278     }
8279
8280   argv[0] = ContainerName;
8281   argv[1] = NULL;
8282   call_args[0] = GroupName;
8283   call_args[1] = NULL;
8284
8285   if (!(rc = mr_query("get_container_list", 1, argv, Moira_getContainerGroup,
8286                       call_args)))
8287     {
8288       if (strlen(GroupName) != 0)
8289         return(0);
8290     }
8291
8292   if (rc)
8293     com_err(whoami, 0, "Unable to get container group from container %s: %s",
8294             ContainerName, error_message(rc));
8295   else
8296     com_err(whoami, 0, "Unable to get container group from container %s",
8297             ContainerName);
8298   
8299   return(0);
8300 }
8301
8302 int Moira_process_machine_container_group(char *MachineName, char* GroupName, 
8303                                           int DeleteMachine)
8304 {
8305   char *argv[3];
8306   long rc;
8307   
8308   if (strcmp(GroupName, "[none]") == 0)
8309     return 0;
8310
8311   argv[0] = GroupName;
8312   argv[1] = "MACHINE";
8313   argv[2] = MachineName;
8314
8315   if (!DeleteMachine)
8316     rc = mr_query("add_member_to_list", 3, argv, NULL, NULL);
8317   else
8318     rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL);
8319
8320   if (rc)
8321     {
8322       com_err(whoami, 0, "Unable to add machine %s to container group%s: %s",
8323               MachineName, GroupName, error_message(rc));
8324     }
8325
8326   return(0);
8327 }
8328
8329 int GetMachineName(char *MachineName)
8330 {
8331   char    *args[2];
8332   char    NewMachineName[1024];
8333   char    *szDot;
8334   int     rc = 0;
8335   int     i;
8336   DWORD   dwLen = 0;
8337   char    *call_args[2];
8338   
8339   // If the address happens to be in the top-level MIT domain, great!
8340   strcpy(NewMachineName, MachineName);
8341
8342   for (i = 0; i < (int)strlen(NewMachineName); i++)
8343     NewMachineName[i] = toupper(NewMachineName[i]);
8344
8345   szDot = strchr(NewMachineName,'.');
8346
8347   if ((szDot) && (!strcasecmp(szDot+1, DOMAIN_SUFFIX)))
8348     {
8349       return(0);
8350     }
8351   
8352   // If not, see if it has a Moira alias in the top-level MIT domain.
8353   memset(NewMachineName, '\0', sizeof(NewMachineName));
8354   args[0] = "*";
8355   args[1] = MachineName;
8356   call_args[0] = NewMachineName;
8357   call_args[1] = NULL;
8358
8359   if (rc = mr_query("get_hostalias", 2, args, ProcessMachineName, call_args))
8360     {
8361       com_err(whoami, 0, "Unable to resolve machine name %s : %s",
8362               MachineName, error_message(rc));
8363       strcpy(MachineName, "");
8364       return(0);
8365     }
8366   
8367   if (strlen(NewMachineName) != 0)
8368     strcpy(MachineName, NewMachineName);
8369   else
8370     strcpy(MachineName, "");
8371
8372   return(0);
8373 }
8374
8375 int ProcessMachineName(int ac, char **av, void *ptr)
8376 {
8377   char    **call_args;
8378   char    MachineName[1024];
8379   char    *szDot;
8380   int     i;
8381   
8382   call_args = ptr;
8383
8384   if (strlen(call_args[0]) == 0)
8385     {
8386       strcpy(MachineName, av[0]);
8387
8388       for (i = 0; i < (int)strlen(MachineName); i++)
8389         MachineName[i] = toupper(MachineName[i]);
8390
8391       szDot = strchr(MachineName,'.');
8392
8393         if ((szDot) && (!strcasecmp(szDot+1,DOMAIN_SUFFIX)))
8394           {
8395             strcpy(call_args[0], MachineName);
8396           }
8397     }
8398
8399   return(0);
8400 }
8401
8402 void SwitchSFU(LDAPMod **mods, int *UseSFU30, int n)
8403 {
8404   int i;
8405   
8406   if (*UseSFU30)
8407     {
8408       for (i = 0; i < n; i++)
8409         {
8410           if (!strcmp(mods[i]->mod_type, "msSFU30UidNumber"))
8411             mods[i]->mod_type = "uidNumber";
8412         }
8413
8414       (*UseSFU30) = 0;
8415     }
8416   else
8417     {
8418       for (i = 0; i < n; i++)
8419         {
8420           if (!strcmp(mods[i]->mod_type, "uidNumber"))
8421             mods[i]->mod_type = "msSFU30UidNumber";
8422         }
8423
8424       (*UseSFU30) = 1;
8425     }
8426 }
8427
8428 int SetHomeDirectory(LDAP *ldap_handle, char *user_name, 
8429                      char *DistinguishedName,
8430                      char *WinHomeDir, char *WinProfileDir,
8431                      char **homedir_v, char **winProfile_v,
8432                      char **drives_v, LDAPMod **mods, 
8433                      int OpType, int n)
8434 {
8435   char cWeight[3];
8436   char cPath[1024];
8437   char path[1024];
8438   char winPath[1024];
8439   char winProfile[1024];
8440   char homeDrive[8];
8441   char homedir[1024];
8442   char apple_homedir[1024];
8443   char *apple_homedir_v[] = {NULL, NULL};
8444   int  last_weight;
8445   int  i;
8446   int  rc;
8447   LDAPMod *DelMods[20];
8448   char *argv[3];
8449   char *save_argv[FS_END];
8450   char *fsgroup_save_argv[2];
8451
8452   memset(homeDrive, '\0', sizeof(homeDrive));
8453   memset(path, '\0', sizeof(path));
8454   memset(winPath, '\0', sizeof(winPath));
8455   memset(winProfile, '\0', sizeof(winProfile));
8456
8457   if(!ActiveDirectory) 
8458     {
8459       if (rc = moira_connect())
8460         {
8461           critical_alert(whoami, "Ldap incremental",
8462                          "Error contacting Moira server : %s",
8463                          error_message(rc));
8464           return;
8465         }
8466       
8467       argv[0] = user_name;
8468
8469       if (!(rc = mr_query("get_filesys_by_label", 1, argv, save_query_info, 
8470                           save_argv)))
8471         {
8472           if(!strcmp(save_argv[FS_TYPE], "FSGROUP") ||
8473              !strcmp(save_argv[FS_TYPE], "MUL"))
8474             {
8475         
8476               argv[0] = save_argv[FS_NAME];
8477               fsgCount = 0;
8478               
8479               if (!(rc = mr_query("get_fsgroup_members", 1, argv, 
8480                                   save_fsgroup_info, fsgroup_save_argv)))
8481                 {
8482                   if(fsgCount)
8483                     {
8484                       argv[0] = fsgroup_save_argv[0];
8485                       
8486                       if (!(rc = mr_query("get_filesys_by_label", 1, argv, 
8487                                           save_query_info, save_argv)))
8488                         {
8489                           strcpy(path, save_argv[FS_PACK]);
8490                         }
8491                     }
8492                 }
8493             }
8494           else
8495             {
8496               strcpy(path, save_argv[FS_PACK]);
8497             }
8498         }
8499       
8500       moira_disconnect();
8501
8502       if (strlen(path))
8503         {
8504           if (!strnicmp(path, AFS, strlen(AFS)))
8505             {
8506               sprintf(homedir, "%s", path);
8507               sprintf(apple_homedir, "%s/MacData", path);
8508               homedir_v[0] = homedir;
8509               apple_homedir_v[0] = apple_homedir;
8510               ADD_ATTR("homeDirectory", homedir_v, OpType);
8511               ADD_ATTR("apple-user-homeDirectory", apple_homedir_v, 
8512                        OpType);
8513             }
8514         }
8515       else
8516         {
8517           homedir_v[0] = "NONE";
8518           apple_homedir_v[0] = "NONE";
8519           ADD_ATTR("homeDirectory", homedir_v, OpType);
8520           ADD_ATTR("apple-user-homeDirectory", apple_homedir_v, 
8521                    OpType);
8522         }
8523
8524       return(n);
8525     }
8526  
8527   if ((!strcasecmp(WinHomeDir, "[afs]")) || 
8528       (!strcasecmp(WinProfileDir, "[afs]")))
8529     {
8530       if (rc = moira_connect())
8531         {
8532           critical_alert(whoami, "Ldap incremental",
8533                          "Error contacting Moira server : %s",
8534                          error_message(rc));
8535           return;
8536         }
8537       
8538       argv[0] = user_name;
8539
8540       if (!(rc = mr_query("get_filesys_by_label", 1, argv, save_query_info, 
8541                           save_argv)))
8542         {
8543           if(!strcmp(save_argv[FS_TYPE], "FSGROUP") ||
8544              !strcmp(save_argv[FS_TYPE], "MUL"))
8545             {
8546         
8547               argv[0] = save_argv[FS_NAME];
8548               fsgCount = 0;
8549               
8550               if (!(rc = mr_query("get_fsgroup_members", 1, argv, 
8551                                   save_fsgroup_info, fsgroup_save_argv)))
8552                 {
8553                   if(fsgCount)
8554                     {
8555                       argv[0] = fsgroup_save_argv[0];
8556                       
8557                       if (!(rc = mr_query("get_filesys_by_label", 1, argv, 
8558                                           save_query_info, save_argv)))
8559                         {
8560                           strcpy(path, save_argv[FS_PACK]);
8561                         }
8562                     }
8563                 }
8564             }
8565           else
8566             {
8567               strcpy(path, save_argv[FS_PACK]);
8568             }
8569         }
8570      
8571       moira_disconnect();
8572
8573       if (strlen(path))
8574         {
8575           if (!strnicmp(path, AFS, strlen(AFS)))
8576             {
8577               AfsToWinAfs(path, winPath);
8578               strcpy(winProfile, winPath);
8579               strcat(winProfile, "\\.winprofile");
8580             }
8581         }
8582       else
8583         return(n);
8584     }
8585
8586     if ((!strcasecmp(WinHomeDir, "[dfs]")) || 
8587         (!strcasecmp(WinProfileDir, "[dfs]")))
8588     {
8589       sprintf(path, "\\\\%s\\dfs\\profiles\\%c\\%s", ldap_domain, 
8590               user_name[0], user_name);
8591
8592       if (!strcasecmp(WinProfileDir, "[dfs]"))
8593         {
8594           strcpy(winProfile, path);
8595           strcat(winProfile, "\\.winprofile");
8596         }
8597
8598       if (!strcasecmp(WinHomeDir, "[dfs]"))
8599         strcpy(winPath, path);
8600     }
8601     
8602     if (!strcasecmp(WinHomeDir, "[local]"))
8603       memset(winPath, '\0', sizeof(winPath));
8604     else if (!strcasecmp(WinHomeDir, "[afs]") || 
8605              !strcasecmp(WinHomeDir, "[dfs]"))
8606       {
8607         strcpy(homeDrive, "H:");
8608       }
8609     else
8610       {
8611         strcpy(winPath, WinHomeDir);
8612         if (!strncmp(WinHomeDir, "\\\\", 2))
8613           {
8614             strcpy(homeDrive, "H:");
8615           }        
8616       }
8617     
8618     // nothing needs to be done if WinProfileDir is [afs].
8619     if (!strcasecmp(WinProfileDir, "[local]"))
8620       memset(winProfile, '\0', sizeof(winProfile));
8621     else if (strcasecmp(WinProfileDir, "[afs]") && 
8622              strcasecmp(WinProfileDir, "[dfs]"))
8623       {
8624         strcpy(winProfile, WinProfileDir);
8625       }
8626     
8627     if (strlen(winProfile) != 0)
8628       {
8629         if (winProfile[strlen(winProfile) - 1] == '\\')
8630           winProfile[strlen(winProfile) - 1] = '\0';
8631       }
8632
8633     if (strlen(winPath) != 0)
8634       {
8635         if (winPath[strlen(winPath) - 1] == '\\')
8636           winPath[strlen(winPath) - 1] = '\0';
8637       }
8638     
8639     if ((winProfile[1] == ':') && (strlen(winProfile) == 2))
8640       strcat(winProfile, "\\");
8641
8642     if ((winPath[1] == ':') && (strlen(winPath) == 2))
8643       strcat(winPath, "\\");
8644     
8645     if (strlen(winPath) == 0)
8646       {
8647         if (OpType == LDAP_MOD_REPLACE)
8648           {
8649             i = 0;
8650             DEL_ATTR("homeDirectory", LDAP_MOD_DELETE);
8651             DelMods[i] = NULL;
8652             //unset homeDirectory attribute for user.
8653             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
8654             free(DelMods[0]);
8655           }
8656       }
8657     else
8658       {
8659         homedir_v[0] = strdup(winPath);
8660         ADD_ATTR("homeDirectory", homedir_v, OpType);
8661       }
8662     
8663     if (strlen(winProfile) == 0)
8664       {
8665         if (OpType == LDAP_MOD_REPLACE)
8666           {
8667             i = 0;
8668             DEL_ATTR("profilePath", LDAP_MOD_DELETE);
8669             DelMods[i] = NULL;
8670             //unset profilePate attribute for user.
8671             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
8672             free(DelMods[0]);
8673           }
8674       }
8675     else
8676       {
8677         winProfile_v[0] = strdup(winProfile);
8678         ADD_ATTR("profilePath", winProfile_v, OpType);
8679       }
8680     
8681     if (strlen(homeDrive) == 0)
8682       {
8683         if (OpType == LDAP_MOD_REPLACE)
8684           {
8685             i = 0;
8686             DEL_ATTR("homeDrive", LDAP_MOD_DELETE);
8687             DelMods[i] = NULL;
8688             //unset homeDrive attribute for user
8689             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
8690             free(DelMods[0]);
8691           }
8692       }
8693     else
8694       {
8695         drives_v[0] = strdup(homeDrive);
8696         ADD_ATTR("homeDrive", drives_v, OpType);
8697       }
8698
8699     return(n);
8700 }
8701
8702 int attribute_update(LDAP *ldap_handle, char *distinguished_name, 
8703                      char *attribute_value, char *attribute, char *user_name)
8704 {
8705   char      *mod_v[] = {NULL, NULL};
8706   LDAPMod   *DelMods[20];
8707   LDAPMod   *mods[20];
8708   int       n;
8709   int       i;
8710   int       rc;
8711   
8712   if (strlen(attribute_value) == 0)
8713     {
8714       i = 0;
8715       DEL_ATTR(attribute, LDAP_MOD_DELETE);
8716       DelMods[i] = NULL;
8717       rc = ldap_modify_s(ldap_handle, distinguished_name, DelMods);
8718       free(DelMods[0]);
8719     }
8720   else
8721     {
8722       n = 0;
8723       mod_v[0] = attribute_value;
8724       ADD_ATTR(attribute, mod_v, LDAP_MOD_REPLACE);
8725       mods[n] = NULL;
8726
8727       if ((rc = ldap_modify_s(ldap_handle, distinguished_name, 
8728                               mods)) != LDAP_SUCCESS)
8729         {
8730           free(mods[0]);
8731           n = 0;
8732           mod_v[0] = attribute_value;
8733           ADD_ATTR(attribute, mod_v, LDAP_MOD_ADD);
8734           mods[n] = NULL;
8735
8736           if ((rc = ldap_modify_s(ldap_handle, distinguished_name, 
8737                                   mods)) != LDAP_SUCCESS)
8738             {
8739               com_err(whoami, 0, "Unable to change the %s attribute for %s "
8740                       "in the directory : %s",
8741                       attribute, user_name, ldap_err2string(rc));
8742             }
8743         }
8744
8745       free(mods[0]);
8746     }
8747   
8748   return(rc);
8749 }
8750
8751 void StringTrim(char *StringToTrim)
8752 {
8753   char *t, *s;
8754   char *save;
8755
8756   save = strdup(StringToTrim);
8757
8758   s = save;
8759
8760   while (isspace(*s))
8761     s++;
8762
8763   /* skip to end of string */
8764   if (*s == '\0')
8765     {
8766       if (*save)
8767         *save = '\0';
8768       strcpy(StringToTrim, save);
8769       return;
8770     }
8771   
8772   for (t = s; *t; t++)
8773     continue;
8774
8775   while (t > s)
8776     {
8777       --t;
8778       if (!isspace(*t))
8779         {
8780           t++;
8781           break;
8782         }
8783     }
8784
8785   if (*t)
8786     *t = '\0';
8787   
8788   strcpy(StringToTrim, s);
8789   return;
8790 }
8791
8792 int ReadConfigFile(char *DomainName)
8793 {
8794     int     Count;
8795     int     i;
8796     int     k;
8797     char    temp[256];
8798     char    temp1[256];
8799     FILE    *fptr;
8800
8801     Count = 0;
8802
8803     sprintf(temp, "%s%s.cfg", CFG_PATH, DomainName);
8804
8805     if ((fptr = fopen(temp, "r")) != NULL)
8806       {
8807         while (fgets(temp, sizeof(temp), fptr) != 0)
8808           {
8809             for (i = 0; i < (int)strlen(temp); i++)
8810               temp[i] = toupper(temp[i]);
8811
8812             if (temp[strlen(temp) - 1] == '\n')
8813               temp[strlen(temp) - 1] = '\0';
8814
8815             StringTrim(temp);
8816
8817             if (strlen(temp) == 0)
8818               continue;
8819
8820             if (!strncmp(temp, DOMAIN, strlen(DOMAIN)))
8821               {
8822                 if (strlen(temp) > (strlen(DOMAIN)))
8823                   {
8824                     strcpy(ldap_domain, &temp[strlen(DOMAIN)]);
8825                     StringTrim(ldap_domain);
8826                   }
8827               }
8828             else if (!strncmp(temp, REALM, strlen(REALM)))
8829               {
8830                 if (strlen(temp) > (strlen(REALM)))
8831                   {
8832                     strcpy(ldap_realm, &temp[strlen(REALM)]);
8833                     StringTrim(ldap_realm);
8834                   }
8835               }
8836             else if (!strncmp(temp, PORT, strlen(PORT)))
8837               {
8838                 if (strlen(temp) > (strlen(PORT)))
8839                   {
8840                     strcpy(ldap_port, &temp[strlen(PORT)]);
8841                     StringTrim(ldap_port);
8842                   }
8843               }
8844             else if (!strncmp(temp, PRINCIPALNAME, strlen(PRINCIPALNAME)))
8845               {
8846                 if (strlen(temp) > (strlen(PRINCIPALNAME)))
8847                   {
8848                     strcpy(PrincipalName, &temp[strlen(PRINCIPALNAME)]);
8849                     StringTrim(PrincipalName);
8850                   }
8851               }
8852             else if (!strncmp(temp, SERVER, strlen(SERVER)))
8853               {
8854                 if (strlen(temp) > (strlen(SERVER)))
8855                   {
8856                     ServerList[Count] = calloc(1, 256);
8857                     strcpy(ServerList[Count], &temp[strlen(SERVER)]);
8858                     StringTrim(ServerList[Count]);
8859                     ++Count;
8860                   }
8861               }
8862             else if (!strncmp(temp, MSSFU, strlen(MSSFU)))
8863               {
8864                 if (strlen(temp) > (strlen(MSSFU)))
8865                   {
8866                     strcpy(temp1, &temp[strlen(MSSFU)]);
8867                     StringTrim(temp1);
8868                     if (!strcmp(temp1, SFUTYPE))
8869                       UseSFU30 = 1;
8870                   }
8871               }
8872             else if (!strncmp(temp, GROUP_SUFFIX, strlen(GROUP_SUFFIX)))
8873               {
8874                 if (strlen(temp) > (strlen(GROUP_SUFFIX)))
8875                   {
8876                     strcpy(temp1, &temp[strlen(GROUP_SUFFIX)]);
8877                     StringTrim(temp1);
8878                     if (!strcasecmp(temp1, "NO")) 
8879                       {
8880                         UseGroupSuffix = 0;
8881                         memset(group_suffix, '\0', sizeof(group_suffix));
8882                       }
8883                   }
8884               }
8885             else if (!strncmp(temp, GROUP_TYPE, strlen(GROUP_TYPE)))
8886               {
8887                 if (strlen(temp) > (strlen(GROUP_TYPE)))
8888                   {
8889                     strcpy(temp1, &temp[strlen(GROUP_TYPE)]);
8890                     StringTrim(temp1);
8891                     if (!strcasecmp(temp1, "UNIVERSAL")) 
8892                       UseGroupUniversal = 1;
8893                   }
8894               }
8895             else if (!strncmp(temp, SET_GROUP_ACE, strlen(SET_GROUP_ACE)))
8896               {
8897                 if (strlen(temp) > (strlen(SET_GROUP_ACE)))
8898                   {
8899                     strcpy(temp1, &temp[strlen(SET_GROUP_ACE)]);
8900                     StringTrim(temp1);
8901                     if (!strcasecmp(temp1, "NO"))
8902                       SetGroupAce = 0;
8903                   }
8904               }
8905             else if (!strncmp(temp, SET_PASSWORD, strlen(SET_PASSWORD)))
8906               {
8907                 if (strlen(temp) > (strlen(SET_PASSWORD)))
8908                   {
8909                     strcpy(temp1, &temp[strlen(SET_PASSWORD)]);
8910                     StringTrim(temp1);
8911                     if (!strcasecmp(temp1, "NO"))
8912                       SetPassword = 0;
8913                   }
8914               }
8915             else if (!strncmp(temp, EXCHANGE, strlen(EXCHANGE)))
8916               {
8917                 if (strlen(temp) > (strlen(EXCHANGE)))
8918                   {
8919                     strcpy(temp1, &temp[strlen(EXCHANGE)]);
8920                     StringTrim(temp1);
8921                     if (!strcasecmp(temp1, "YES"))
8922                       Exchange = 1;
8923                   }
8924               }
8925             else if (!strncmp(temp, PROCESS_MACHINE_CONTAINER, 
8926                               strlen(PROCESS_MACHINE_CONTAINER)))
8927               {
8928                 if (strlen(temp) > (strlen(PROCESS_MACHINE_CONTAINER)))
8929                   {
8930                     strcpy(temp1, &temp[strlen(PROCESS_MACHINE_CONTAINER)]);
8931                     StringTrim(temp1);
8932                     if (!strcasecmp(temp1, "NO"))
8933                       ProcessMachineContainer = 0;
8934                   }
8935               }
8936             else if (!strncmp(temp, ACTIVE_DIRECTORY, 
8937                               strlen(ACTIVE_DIRECTORY)))
8938               {
8939                 if (strlen(temp) > (strlen(ACTIVE_DIRECTORY)))
8940                   {
8941                     strcpy(temp1, &temp[strlen(ACTIVE_DIRECTORY)]);
8942                     StringTrim(temp1);
8943                     if (!strcasecmp(temp1, "NO"))
8944                       ActiveDirectory = 0;
8945                   }
8946               }
8947             else if (!strncmp(temp, GROUP_POPULATE_MEMBERS, 
8948                               strlen(GROUP_POPULATE_MEMBERS)))
8949               {
8950                 if (strlen(temp) > (strlen(GROUP_POPULATE_MEMBERS)))
8951                   {
8952                     strcpy(temp1, &temp[strlen(GROUP_POPULATE_MEMBERS)]);
8953                     StringTrim(temp1);
8954                     if (!strcasecmp(temp1, "DELETE")) 
8955                       {
8956                         GroupPopulateDelete = 1;
8957                       }
8958                   }
8959               }
8960             else if (!strncmp(temp, MAX_MEMBERS, strlen(MAX_MEMBERS)))
8961               {
8962                 if (strlen(temp) > (strlen(MAX_MEMBERS)))
8963                   {
8964                     strcpy(temp1, &temp[strlen(MAX_MEMBERS)]);
8965                     StringTrim(temp1);
8966                     max_group_members = atoi(temp1);
8967                   }
8968               }
8969             else
8970               {
8971                 if (strlen(ldap_domain) != 0)
8972                   {
8973                     memset(ldap_domain, '\0', sizeof(ldap_domain));
8974                     break;
8975                   }
8976
8977                 if (strlen(temp) != 0)
8978                   strcpy(ldap_domain, temp);
8979               }
8980           }
8981         fclose(fptr);
8982       }
8983     
8984     if (strlen(ldap_domain) == 0)
8985       {
8986       strcpy(ldap_domain, DomainName);
8987       }
8988
8989     if (Count == 0)
8990         return(0);
8991
8992     for (i = 0; i < Count; i++)
8993       {
8994         if (ServerList[i] != 0)
8995           {
8996             for (k = 0; k < (int)strlen(ServerList[i]); k++)
8997               ServerList[i][k] = toupper(ServerList[i][k]);
8998           }
8999       }
9000     
9001     return(0);
9002 }
9003
9004 int ReadDomainList()
9005 {
9006   int     Count;
9007   int     i;
9008   char    temp[128];
9009   char    temp1[128];
9010   FILE    *fptr;
9011   unsigned char c[11];
9012   unsigned char stuff[256];
9013   int     rc;
9014   int     ok;
9015
9016   Count = 0;
9017   sprintf(temp, "%s%s", CFG_PATH, WINADCFG);
9018
9019   if ((fptr = fopen(temp, "r")) != NULL)
9020     {
9021       while (fgets(temp, sizeof(temp), fptr) != 0)
9022         {
9023           for (i = 0; i < (int)strlen(temp); i++)
9024             temp[i] = toupper(temp[i]);
9025
9026           if (temp[strlen(temp) - 1] == '\n')
9027             temp[strlen(temp) - 1] = '\0';
9028
9029           StringTrim(temp);
9030
9031           if (strlen(temp) == 0)
9032             continue;
9033
9034           if (!strncmp(temp, DOMAIN, strlen(DOMAIN)))
9035             {
9036               if (strlen(temp) > (strlen(DOMAIN)))
9037                 {
9038                   strcpy(temp1, &temp[strlen(DOMAIN)]);
9039                   StringTrim(temp1);
9040                   strcpy(temp, temp1);
9041                 }
9042             }
9043           
9044           strcpy(DomainNames[Count], temp);
9045           StringTrim(DomainNames[Count]);
9046           ++Count;
9047         }
9048
9049       fclose(fptr);
9050     }
9051
9052   if (Count == 0)
9053     {
9054       critical_alert(whoami, "incremental", "%s", "ldap.incr cannot run due to a "
9055                      "configuration error in ldap.cfg");
9056       return(1);
9057     }
9058   
9059   return(0);
9060 }
9061
9062 int email_isvalid(const char *address) {
9063   int        count = 0;
9064   const char *c, *domain;
9065   static char *rfc822_specials = "()<>@,;:\\\"[]";
9066
9067   if(address[strlen(address) - 1] == '.') 
9068     return 0;
9069     
9070   /* first we validate the name portion (name@domain) */
9071   for (c = address;  *c;  c++) {
9072     if (*c == '\"' && (c == address || *(c - 1) == '.' || *(c - 1) == 
9073                        '\"')) {
9074       while (*++c) {
9075         if (*c == '\"') 
9076           break;
9077         if (*c == '\\' && (*++c == ' ')) 
9078           continue;
9079         if (*c <= ' ' || *c >= 127) 
9080           return 0;
9081       }
9082
9083       if (!*c++) 
9084         return 0;
9085       if (*c == '@') 
9086         break;
9087       if (*c != '.') 
9088         return 0;
9089       continue;
9090     }
9091
9092     if (*c == '@') 
9093       break;
9094     if (*c <= ' ' || *c >= 127) 
9095       return 0;
9096     if (strchr(rfc822_specials, *c)) 
9097       return 0;
9098   }
9099
9100   if (c == address || *(c - 1) == '.') 
9101     return 0;
9102
9103   /* next we validate the domain portion (name@domain) */
9104   if (!*(domain = ++c)) return 0;
9105   do {
9106     if (*c == '.') {
9107       if (c == domain || *(c - 1) == '.') 
9108         return 0;
9109       count++;
9110     }
9111     if (*c <= ' ' || *c >= 127) 
9112       return 0;
9113     if (strchr(rfc822_specials, *c)) 
9114       return 0;
9115   } while (*++c);
9116
9117   return (count >= 1);
9118 }
9119
9120 int find_homeMDB(LDAP *ldap_handle, char *dn_path, char **homeMDB, 
9121              char **homeServerName) 
9122 {
9123   LK_ENTRY *group_base;
9124   LK_ENTRY *sub_group_base;
9125   LK_ENTRY *gPtr;
9126   LK_ENTRY *sub_gPtr;
9127   int      group_count;
9128   int      sub_group_count;
9129   char     filter[1024];
9130   char     sub_filter[1024];
9131   char     search_path[1024];
9132   char     range[1024];
9133   char     *attr_array[3];
9134   char     *s;
9135   int      homeMDB_count = -1;
9136   int      rc;
9137   int      i;
9138   int      mdbbl_count;
9139   int      rangeStep = 1500;
9140   int      rangeLow = 0;
9141   int      rangeHigh = rangeLow + (rangeStep - 1);
9142   int      isLast = 0;
9143
9144   /* Grumble..... microsoft not making it searchable from the root *grr* */
9145
9146   memset(filter, '\0', sizeof(filter));
9147   memset(search_path, '\0', sizeof(search_path));
9148   
9149   sprintf(filter, "(objectClass=msExchMDB)");
9150   sprintf(search_path, "CN=Configuration,%s", dn_path);
9151   attr_array[0] = "distinguishedName";
9152   attr_array[1] = NULL;
9153   
9154   group_base = NULL;
9155   group_count = 0;
9156   
9157   if ((rc = linklist_build(ldap_handle, search_path, filter, attr_array,
9158                            &group_base, &group_count, 
9159                            LDAP_SCOPE_SUBTREE)) != 0) 
9160     {
9161       com_err(whoami, 0, "Unable to find msExchMDB %s",
9162               ldap_err2string(rc));
9163       return(rc);
9164     }
9165   
9166   if (group_count) 
9167     {
9168       gPtr = group_base;
9169       
9170       while(gPtr) {
9171         if (((s = strstr(gPtr->dn, "Public")) != (char *) NULL) ||
9172             ((s = strstr(gPtr->dn, "Recover")) != (char *) NULL) || 
9173             ((s = strstr(gPtr->dn, "Reserve")) != (char *) NULL))
9174           {
9175             gPtr = gPtr->next;
9176             continue;
9177           }
9178
9179         /* 
9180          * Due to limits in active directory we need to use the LDAP
9181          * range semantics to query and return all the values in 
9182          * large lists, we will stop increasing the range when
9183          * the result count is 0.
9184          */
9185
9186         i = 0;  
9187         mdbbl_count = 0;
9188
9189         for(;;) 
9190           {
9191             memset(sub_filter, '\0', sizeof(sub_filter));
9192             memset(range, '\0', sizeof(range));
9193             sprintf(sub_filter, "(objectClass=msExchMDB)");
9194
9195             if(isLast)
9196               sprintf(range, "homeMDBBL;Range=%d-*", rangeLow);
9197             else 
9198               sprintf(range, "homeMDBBL;Range=%d-%d", rangeLow, rangeHigh);
9199
9200             attr_array[0] = range;
9201             attr_array[1] = NULL;
9202             
9203             sub_group_base = NULL;
9204             sub_group_count = 0;
9205             
9206             if ((rc = linklist_build(ldap_handle, gPtr->dn, sub_filter, 
9207                                      attr_array, &sub_group_base, 
9208                                      &sub_group_count, 
9209                                      LDAP_SCOPE_SUBTREE)) != 0) 
9210               {
9211                 com_err(whoami, 0, "Unable to find homeMDBBL %s",
9212                         ldap_err2string(rc));
9213                 return(rc);
9214               }
9215
9216             if(!sub_group_count)
9217               {
9218                 if(isLast) 
9219                   {
9220                     isLast = 0;
9221                     rangeLow = 0;
9222                     rangeHigh = rangeLow + (rangeStep - 1);
9223                     break;
9224                   }
9225                 else
9226                   isLast++;
9227               }
9228
9229             mdbbl_count += sub_group_count;
9230             rangeLow = rangeHigh + 1;
9231             rangeHigh = rangeLow + (rangeStep - 1);
9232           }
9233
9234         /* First time through, need to initialize or update the least used */
9235         
9236         com_err(whoami, 0, "Mail store %s, count %d", gPtr->dn, 
9237                 mdbbl_count);
9238
9239         if(mdbbl_count < homeMDB_count || homeMDB_count == -1) 
9240           {
9241             homeMDB_count = mdbbl_count; 
9242             *homeMDB = strdup(gPtr->dn);
9243           }
9244
9245         gPtr = gPtr->next;
9246         linklist_free(sub_group_base);
9247       }
9248     }
9249
9250   linklist_free(group_base);
9251   
9252   /* 
9253    * Ok found the server least allocated need to now query to get its
9254    * msExchHomeServerName so we can set it as a user attribute
9255    */
9256   
9257   attr_array[0] = "legacyExchangeDN";
9258   attr_array[1] = NULL; 
9259   
9260   group_count = 0;
9261   group_base = NULL;
9262   
9263   if ((rc = linklist_build(ldap_handle, *homeMDB, filter, 
9264                            attr_array, &group_base, 
9265                            &group_count, 
9266                            LDAP_SCOPE_SUBTREE)) != 0) 
9267     {
9268       com_err(whoami, 0, "Unable to find msExchHomeServerName %s",
9269               ldap_err2string(rc));
9270       return(rc);
9271     }  
9272   
9273   if(group_count) 
9274     {
9275       *homeServerName = strdup(group_base->value);
9276       if((s = strrchr(*homeServerName, '/')) != (char *) NULL) 
9277         {
9278           *s = '\0';
9279         }
9280     } 
9281
9282   linklist_free(group_base);
9283   
9284   return(rc);
9285 }
9286       
9287 char *lowercase(char *s)
9288 {
9289   char *p;
9290
9291   for (p = s; *p; p++)
9292     {
9293       if (isupper(*p))
9294         *p = tolower(*p);
9295     }
9296   return s;
9297 }
9298
9299 char *uppercase(char *s)
9300 {
9301   char *p;
9302
9303   for (p = s; *p; p++)
9304     {
9305       if (islower(*p))
9306         *p = toupper(*p);
9307     }
9308   return s;
9309 }
9310
9311 char *escape_string(char *s)
9312 {
9313   char *p, *q;
9314   char string[1024];
9315   char temp[1024];
9316   int i = 0;
9317   int spaces = 0;
9318
9319   if(ActiveDirectory) {
9320     return strdup(s);
9321   }
9322
9323   memset(string, '\0', sizeof(string));
9324
9325   q = s;
9326
9327   /* Escape any special characters */
9328
9329   for(; *q != '\0'; q++) {
9330     if(*q == ',')
9331       string[i++] = '\\';
9332     if(*q == '+') 
9333       string[i++] = '\\';
9334     if(*q == '"') 
9335       string[i++] = '\\';
9336     if(*q == '\\') 
9337       string[i++] = '\\';
9338     if(*q == '<') 
9339       string[i++] = '\\';
9340     if(*q == '>') 
9341       string[i++] = '\\';
9342     if(*q == ';')
9343       string[i++] = '\\';
9344     if(*q == '#')
9345       string[i++] = '\\';
9346     if(*q == '=')
9347       string[i++] = '\\';
9348
9349     string[i++] = *q;
9350   }
9351
9352   return strdup(string);
9353 }
9354
9355 int save_query_info(int argc, char **argv, void *hint)
9356 {
9357   int i;
9358   char **nargv = hint;
9359
9360   for(i = 0; i < argc; i++)
9361     nargv[i] = strdup(argv[i]);
9362
9363   return MR_CONT;
9364 }
9365
9366 int save_fsgroup_info(int argc, char **argv, void *hint)
9367 {
9368   int i;
9369   char **nargv = hint;
9370
9371   if(!fsgCount) 
9372     {
9373       for(i = 0; i < argc; i++)
9374         nargv[i] = strdup(argv[i]);
9375
9376       fsgCount++;
9377     }
9378
9379   return MR_CONT;
9380 }
9381
9382 int contains_member(LDAP *ldap_handle, char *dn_path, char *group_name, 
9383                     char *UserOu, char *user_name)
9384 {
9385   char         search_filter[1024];
9386   char         *attr_array[3];
9387   LK_ENTRY     *group_base;
9388   int          group_count;
9389   int          rc;
9390   char         temp[256];
9391
9392   if(ActiveDirectory)
9393     {
9394       sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
9395     }
9396   else
9397     {
9398       if(!strcmp(UserOu, user_ou))
9399         sprintf(temp, "uid=%s,%s,%s", user_name, UserOu, dn_path);
9400       else
9401         sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
9402     }
9403
9404   group_base = NULL;
9405   group_count = 0;
9406   
9407   sprintf(search_filter, "(&(objectClass=group)(cn=%s)(member=%s))",
9408           group_name, temp);
9409
9410   attr_array[0] = "mitMoiraId";
9411   attr_array[1] = NULL;
9412
9413   if ((rc = linklist_build(ldap_handle, dn_path, search_filter, 
9414                            attr_array, &group_base, &group_count,
9415                            LDAP_SCOPE_SUBTREE)) != 0)
9416     {
9417       com_err(whoami, 0, "Unable to check group %s for membership of %s : %s",
9418               group_name, user_name, ldap_err2string(rc));
9419       return(-1);
9420     }
9421           
9422   if (group_count)
9423     {
9424       rc = 1;
9425     }
9426   else 
9427     {
9428       rc = 0;
9429     }
9430
9431   linklist_free(group_base);
9432   group_count = 0;
9433   group_base = NULL;
9434
9435   return(rc);
9436 }
This page took 0.793902 seconds and 3 git commands to generate.