]> andersk Git - moira.git/blob - incremental/ldap/winad.c
More changes from mark.
[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   if ((atoi(av[U_STATE]) != US_NO_PASSWD) && 
5128       (atoi(av[U_STATE]) != US_REGISTERED))
5129     {
5130       userAccountControl |= UF_ACCOUNTDISABLE;
5131
5132       if (Exchange)
5133         {
5134           hide_address_lists_v[0] = "TRUE";
5135
5136           ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
5137                    LDAP_MOD_ADD);
5138
5139           /*
5140           sprintf(address_book, "%s%s", GLOBAL_ADDRESS_LIST_PREFIX, 
5141                   call_args[1]);
5142           address_book_v[0] = strdup(address_book);
5143           memset(address_book, '\0', sizeof(address_book));
5144           sprintf(address_book, "%s%s", ADDRESS_LIST_PREFIX, call_args[1]);
5145           address_book_v[1] = strdup(address_book);
5146           memset(address_book, '\0', sizeof(address_book));
5147           sprintf(address_book, "%s%s", EMAIL_ADDRESS_LIST_PREFIX, 
5148                   call_args[1]);
5149           address_book_v[2] = strdup(address_book);
5150           memset(address_book, '\0', sizeof(address_book));
5151           sprintf(address_book, "%s%s", ALL_ADDRESS_LIST_PREFIX, 
5152                   call_args[1]);
5153           address_book_v[3] = strdup(address_book);
5154           memset(address_book, '\0', sizeof(address_book));
5155           
5156           ADD_ATTR("showInAddressBook", address_book_v,
5157                    LDAP_MOD_ADD);
5158           */
5159         }
5160     }
5161
5162   sprintf(userAccountControlStr, "%ld", userAccountControl);
5163   userAccountControl_v[0] = userAccountControlStr;
5164   userPrincipalName_v[0] = upn;
5165   
5166   if(ActiveDirectory)
5167     cn_v[0] = user_name;
5168   else
5169     cn_v[0] = displayName;
5170     
5171   name_v[0] = user_name;
5172   desc_v[0] = "Auto account created by Moira";
5173   mail_v[0] = mail;
5174   givenName_v[0] = av[U_FIRST];
5175
5176   if(ActiveDirectory)
5177     sn_v[0] = av[U_LAST];
5178   else
5179     if(strlen(av[U_LAST]))
5180       sn_v[0] = av[U_LAST];
5181     else
5182       sn_v[0] = av[U_NAME];
5183
5184   displayName_v[0] = displayName;
5185   mail_nickname_v[0] = user_name;
5186   o_v[0] = "Massachusetts Institute of Technology";
5187
5188   sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
5189   sprintf(principal, "%s@%s", user_name, PRIMARY_REALM);
5190   altSecurityIdentities_v[0] = temp;    
5191   principal_v[0] = principal;
5192
5193   if(ActiveDirectory)
5194     sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, call_args[1]);
5195   else
5196     sprintf(new_dn, "uid=%s,%s,%s", user_name, user_ou, call_args[1]);
5197
5198   sprintf(mail,"%s@%s", user_name, lowercase(ldap_domain));
5199   if(Exchange)
5200     sprintf(contact_mail, "%s@exchange-forwarding.mit.edu", user_name);
5201   else
5202     sprintf(contact_mail, "%s@mit.edu", user_name);    
5203   sprintf(query_base_dn, "%s%s", ADDRESS_LIST_PREFIX, call_args[1]);
5204   query_base_dn_v[0] = query_base_dn;
5205   sprintf(alt_recipient, "cn=%s@exchange-forwarding.mit.edu,%s,%s", user_name,
5206           contact_ou, call_args[1]);
5207   sprintf(search_string, "@%s", uppercase(ldap_domain));
5208
5209   if (Exchange)
5210     {
5211       if(contact_create((LDAP *)call_args[0], call_args[1], contact_mail, 
5212                         contact_ou))
5213         {
5214           com_err(whoami, 0, "Unable to create user contact %s", 
5215                   contact_mail);
5216         }
5217       
5218       if(find_homeMDB((LDAP *)call_args[0], call_args[1], &homeMDB, 
5219                       &homeServerName)) 
5220         {
5221           com_err(whoami, 0, "Unable to locate homeMB and homeServerName");
5222           return(1);
5223         }
5224       
5225       com_err(whoami, 0, "homeMDB:%s", homeMDB);
5226       com_err(whoami, 0, "homeServerName:%s", homeServerName);
5227   
5228       homeMDB_v[0] = homeMDB;
5229       homeServerName_v[0] = homeServerName; 
5230     }
5231
5232   n = 0;
5233
5234   ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
5235   
5236   if(ActiveDirectory) 
5237     {
5238       ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
5239     }
5240   else
5241     {
5242       ADD_ATTR("objectClass", objectClass_ldap_v, LDAP_MOD_ADD);
5243     }
5244
5245   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
5246   ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_ADD);
5247   ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_ADD);
5248   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
5249   ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
5250
5251   if (Exchange)
5252     {
5253       ADD_ATTR("msExchQueryBaseDN", query_base_dn_v, LDAP_MOD_ADD);
5254       ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_ADD);
5255       ADD_ATTR("homeMDB", homeMDB_v, LDAP_MOD_ADD);
5256       mdbUseDefaults_v[0] = "TRUE";
5257       ADD_ATTR("mdbUseDefaults", mdbUseDefaults_v, LDAP_MOD_ADD);
5258       ADD_ATTR("msExchHomeServerName", homeServerName_v, LDAP_MOD_ADD); 
5259       
5260       argv[0] = user_name;
5261     
5262       if (!(rc = mr_query("get_pobox", 1, argv, save_query_info, save_argv)))
5263         {
5264           if(!strcmp(save_argv[1], "EXCHANGE") || 
5265              (strstr(save_argv[3], search_string) != NULL))
5266             {
5267               argv[0] = exchange_acl;
5268               argv[1] = "USER";
5269               argv[2] = user_name;
5270               
5271               rc = mr_query("add_member_to_list", 3, argv, NULL, NULL);
5272               
5273               if ((rc) && (rc != MR_EXISTS))
5274                 {
5275                   com_err(whoami, 0, "Unable to add user %s to %s: %s",
5276                           user_name, exchange_acl, error_message(rc));
5277                 }
5278
5279               if(!strcmp(save_argv[1], "SPLIT") ||
5280                  !strcmp(save_argv[1], "SMTP")) {
5281                 
5282                 deliver_and_redirect_v[0] = "TRUE";
5283                 alt_recipient_v[0] = alt_recipient;
5284
5285                 ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_ADD);
5286                 ADD_ATTR("deliverAndRedirect", deliver_and_redirect_v,
5287                          LDAP_MOD_ADD);
5288               }
5289             }
5290           else 
5291             {
5292               alt_recipient_v[0] = alt_recipient;
5293               ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_ADD);
5294             }
5295         }
5296       else
5297         {
5298           alt_recipient_v[0] = alt_recipient;
5299           ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_ADD);
5300           
5301           com_err(whoami, 0, "Unable to fetch pobox for %s", user_name);
5302         }
5303     }
5304   else
5305     {
5306       mail_v[0] = contact_mail;
5307       ADD_ATTR("mail", mail_v, LDAP_MOD_ADD);
5308
5309       if(!ActiveDirectory)
5310         {
5311           ADD_ATTR("mitMoiraMail", mail_v, LDAP_MOD_ADD);
5312         }
5313     }
5314
5315   if(strlen(av[U_FIRST])) {
5316     ADD_ATTR("givenName", givenName_v, LDAP_MOD_ADD);
5317   }
5318
5319   if(strlen(av[U_LAST]) || strlen(av[U_NAME])) {
5320     ADD_ATTR("sn", sn_v, LDAP_MOD_ADD);
5321   }
5322
5323   if(strlen(av[U_FIRST]) || strlen(av[U_MIDDLE]) || strlen(av[U_LAST])) {
5324     ADD_ATTR("displayName", displayName_v, LDAP_MOD_ADD);
5325
5326     if(!ActiveDirectory)
5327       {
5328         ADD_ATTR("eduPersonNickname", displayName_v, LDAP_MOD_ADD);      
5329       }
5330   } else {
5331     ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
5332
5333     if(!ActiveDirectory)
5334       {
5335         ADD_ATTR("eduPersonNickname", name_v, LDAP_MOD_ADD);            
5336       }
5337   }
5338
5339   if (strlen(av[U_MIDDLE]) == 1) {
5340     initials_v[0] = av[U_MIDDLE];
5341     ADD_ATTR("initials", initials_v, LDAP_MOD_ADD);
5342   }
5343
5344   if (strlen(call_args[2]) != 0)    
5345     {
5346       mitMoiraId_v[0] = call_args[2];
5347       ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_ADD); 
5348     }
5349
5350   ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_ADD);
5351
5352   if(!ActiveDirectory)
5353     {
5354       loginshell_v[0] = av[U_SHELL];
5355       mitMoiraClass_v[0] = av[U_CLASS];
5356       mitMoiraStatus_v[0] = av[U_STATE];
5357       ADD_ATTR("loginShell", loginshell_v, LDAP_MOD_ADD);
5358       ADD_ATTR("uid", samAccountName_v, LDAP_MOD_ADD);
5359       ADD_ATTR("eduPersonPrincipalName", mail_v, LDAP_MOD_ADD);
5360       ADD_ATTR("o", o_v, LDAP_MOD_ADD);
5361       ADD_ATTR("mitMoiraClass", mitMoiraClass_v, LDAP_MOD_ADD);
5362       ADD_ATTR("mitMoiraStatus", mitMoiraStatus_v, LDAP_MOD_ADD);
5363     }
5364
5365   if (strlen(av[U_UID]) != 0)
5366     {
5367       uid_v[0] = av[U_UID];
5368
5369       if(ActiveDirectory) 
5370         {
5371           ADD_ATTR("uid", uid_v, LDAP_MOD_ADD);
5372         }
5373       else
5374         {
5375           gid_v[0] = "101";
5376           ADD_ATTR("uidNumber", uid_v, LDAP_MOD_ADD);
5377           ADD_ATTR("gidNumber", gid_v, LDAP_MOD_ADD);
5378         }
5379
5380       if(ActiveDirectory)
5381         {
5382           if (!UseSFU30)
5383             {
5384               ADD_ATTR("uidNumber", uid_v, LDAP_MOD_ADD);
5385             }
5386           else
5387             {
5388               ADD_ATTR("msSFU30UidNumber", uid_v, LDAP_MOD_ADD);
5389             }
5390         }
5391     }
5392
5393   if ((strlen(av[U_MITID]) != 0) && (av[U_MITID][0] == '9'))
5394       mitid_v[0] = av[U_MITID];
5395   else
5396       mitid_v[0] = "none";
5397
5398   ADD_ATTR("employeeID", mitid_v, LDAP_MOD_ADD);
5399
5400   n = SetHomeDirectory((LDAP *)call_args[0], user_name, new_dn, 
5401                        WinHomeDir, WinProfileDir, homedir_v, winProfile_v,
5402                        drives_v, mods, LDAP_MOD_ADD, n);
5403   
5404   if(ActiveDirectory) 
5405     {
5406       sprintf(filter_exp, "(sAMAccountName=%s)", "UserTemplate.u");
5407       sprintf(search_path, "%s,%s", security_template_ou, call_args[1]);
5408       attr_array[0] = "sAMAccountName";
5409       attr_array[1] = NULL;
5410       group_count = 0;
5411       group_base = NULL;
5412       
5413       if ((rc = linklist_build((LDAP *)call_args[0], search_path, filter_exp, 
5414                                attr_array, &group_base, &group_count, 
5415                                LDAP_SCOPE_SUBTREE) != 0))
5416         return(1);
5417       
5418       if (group_count != 1)
5419         {
5420           com_err(whoami, 0, "Unable to process user security template: %s - "
5421                   "security not set", "UserTemplate.u");
5422           return(1);
5423         }
5424       
5425       strcpy(TemplateDn, group_base->dn);
5426       strcpy(TemplateSamName, group_base->value);
5427       linklist_free(group_base);
5428       group_base = NULL;
5429       group_count = 0;
5430       
5431       rc = ldap_search_ext_s((LDAP *)call_args[0], search_path, 
5432                              LDAP_SCOPE_SUBTREE, filter_exp, NULL, 0, 
5433                              apsServerControls, NULL,
5434                              NULL, 0, &psMsg);
5435       
5436       if ((psMsg = ldap_first_entry((LDAP *)call_args[0], psMsg)) == NULL)
5437         {
5438           com_err(whoami, 0, "Unable to find user security template: %s - "
5439                   "security not set", "UserTemplate.u");
5440           return(1);
5441         }
5442       
5443       ppsValues = ldap_get_values_len((LDAP *)call_args[0], psMsg, 
5444                                       "ntSecurityDescriptor");
5445       if (ppsValues == NULL)
5446         {
5447           com_err(whoami, 0, "Unable to find user security template: %s - "
5448                   "security not set", "UserTemplate.u");
5449           return(1);
5450         }
5451       
5452       ADD_ATTR("ntSecurityDescriptor", (char **)ppsValues,
5453                LDAP_MOD_REPLACE | LDAP_MOD_BVALUES); 
5454     }
5455
5456   mods[n] = NULL;
5457
5458   rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
5459
5460   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
5461     {
5462       OldUseSFU30 = UseSFU30;
5463       SwitchSFU(mods, &UseSFU30, n);
5464       if (OldUseSFU30 != UseSFU30)
5465         rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
5466     }
5467
5468   for (i = 0; i < n; i++)
5469     free(mods[i]);
5470
5471   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
5472     {
5473       com_err(whoami, 0, "Unable to create user %s : %s",
5474               user_name, ldap_err2string(rc));
5475       callback_rc = rc;
5476       return(rc);
5477     }
5478
5479   if ((rc == LDAP_SUCCESS) && (SetPassword))
5480     {
5481       if ((rc = set_password(sam_name, "", ldap_domain)) != 0)
5482         {
5483           ad_kdc_disconnect();
5484           if (!ad_server_connect(default_server, ldap_domain))
5485             {
5486               com_err(whoami, 0, "Unable to set password for user %s : %s",
5487                       user_name, 
5488                       "cannot get changepw ticket from windows domain");
5489             }
5490           else
5491             {
5492               if ((rc = set_password(sam_name, "", ldap_domain)) != 0)
5493                 {
5494                   com_err(whoami, 0, "Unable to set password for user %s "
5495                           ": %ld", user_name, rc);
5496                 }
5497             }
5498         }
5499     }
5500
5501   if(!ActiveDirectory) 
5502     {
5503       if (rc = moira_connect())
5504         {
5505           critical_alert(whoami, "Ldap incremental", 
5506                          "Error contacting Moira server : %s",
5507                          error_message(rc));
5508           return;
5509         }
5510   
5511       argv[0] = filesys_name;
5512
5513       if (!(rc = mr_query("get_filesys_by_label", 1, argv, save_query_info, 
5514                           save_argv)))
5515         {
5516           n = 0;
5517           ADD_ATTR("mitMoiraIMAPAddress", mit_moira_imap_address_v, 
5518                    LDAP_MOD_REPLACE);
5519           mods[n] = NULL;
5520           rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5521           
5522           if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
5523             rc = LDAP_SUCCESS;
5524
5525           if(rc)
5526             com_err(whoami, 0, 
5527                     "Unable to set the mitMoiraIMAPAddress for %s : %s",
5528                     user_name, ldap_err2string(rc));
5529
5530           sprintf(temp, "%s@%s", user_name, save_argv[FS_MACHINE]);
5531           
5532           mit_moira_imap_address_v[0]  = temp;
5533                 
5534           n = 0;
5535           ADD_ATTR("mitMoiraIMAPAddress", mit_moira_imap_address_v, 
5536                    LDAP_MOD_ADD);
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, "Unable to set the mitMoiraIMAPAddress for " 
5545                     "%s : %s", user_name, ldap_err2string(rc));   
5546         } else if(rc==MR_NO_MATCH) {
5547           
5548           n = 0;
5549           ADD_ATTR("mitMoiraIMAPAddress", mit_moira_imap_address_v, 
5550                    LDAP_MOD_REPLACE);
5551           mods[n] = NULL;
5552           rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5553           
5554           if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
5555             rc = LDAP_SUCCESS;
5556
5557           if(rc)
5558             com_err(whoami, 0, 
5559                     "Unable to set the mitMoiraIMAPAddress for %s : %s",
5560                     user_name, ldap_err2string(rc));
5561
5562         }
5563
5564       argv[0] = user_name;
5565     
5566       if (!(rc = mr_query("get_pobox", 1, argv, save_query_info, save_argv)))
5567         {
5568           n = 0;
5569           ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_REPLACE);
5570           mods[n] = NULL;
5571           rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5572            
5573           if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
5574             rc = LDAP_SUCCESS;
5575
5576           if(rc)
5577             com_err(whoami, 0,
5578                     "Unable to set the mailRoutingAddress for %s : %s",
5579                     user_name, ldap_err2string(rc));
5580
5581           p = strdup(save_argv[3]);
5582           
5583           if((c = strchr(p, ',')) != NULL) {
5584             q = strtok(p, ",");
5585             StringTrim(q);
5586
5587             if ((c = strchr(q, '@')) == NULL)
5588               sprintf(temp, "%s@mit.edu", q);
5589             else
5590               sprintf(temp, "%s", q);
5591
5592             if(email_isvalid(temp) && atoi(av[U_STATE]) != US_DELETED) 
5593               {
5594                 mail_routing_v[0]  = temp;
5595
5596                 n = 0;
5597                 ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
5598                 mods[n] = NULL;
5599                 rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5600                 
5601                 if (rc == LDAP_ALREADY_EXISTS || 
5602                     rc == LDAP_TYPE_OR_VALUE_EXISTS)
5603                   rc = LDAP_SUCCESS;
5604                 
5605                 if(rc)
5606                   com_err(whoami, 0, 
5607                           "Unable to set the mailRoutingAddress for %s : %s",
5608                           user_name, ldap_err2string(rc));
5609               }
5610
5611             while((q = strtok(NULL, ",")) != NULL) {
5612               StringTrim(q);
5613
5614               if((c = strchr(q, '@')) == NULL)
5615                 sprintf(temp, "%s@mit.edu", q);
5616               else
5617                 sprintf(temp, "%s", q);
5618
5619               if(email_isvalid(temp) && atoi(av[U_STATE]) != US_DELETED)
5620                 {
5621                   mail_routing_v[0]  = temp;
5622                   
5623                   n = 0;
5624                   ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
5625                   mods[n] = NULL;
5626                   rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5627                   
5628                   if (rc == LDAP_ALREADY_EXISTS || 
5629                       rc == LDAP_TYPE_OR_VALUE_EXISTS)
5630                     rc = LDAP_SUCCESS;
5631                   
5632                   if(rc)
5633                     com_err(whoami, 0, 
5634                             "Unable to set the mailRoutingAddress for %s : %s",
5635                             user_name, ldap_err2string(rc));
5636                 }
5637             }
5638           } else {
5639             StringTrim(p);
5640
5641             if((c = strchr(p, '@')) == NULL)
5642               sprintf(temp, "%s@mit.edu", p);
5643             else
5644               sprintf(temp, "%s", p);
5645
5646             if(email_isvalid(temp) && atoi(av[U_STATE]) != US_DELETED) 
5647               {
5648                 mail_routing_v[0]  = temp;
5649                 
5650                 n = 0;
5651                 ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
5652                 mods[n] = NULL;
5653                 rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5654                 
5655                 if (rc == LDAP_ALREADY_EXISTS || 
5656                     rc == LDAP_TYPE_OR_VALUE_EXISTS)
5657                   rc = LDAP_SUCCESS;
5658                 
5659                 if(rc)
5660                   com_err(whoami, 0, 
5661                           "Unable to set the mailRoutingAddress for %s : %s",
5662                           user_name, ldap_err2string(rc));
5663               }
5664           }
5665         }
5666       moira_disconnect();
5667     }
5668
5669   return(0);
5670 }
5671
5672 int user_change_status(LDAP *ldap_handle, char *dn_path, 
5673                        char *user_name, char *MoiraId,
5674                        int operation)
5675 {
5676   char      filter[128];
5677   char      *attr_array[3];
5678   char      temp[256];
5679   char      distinguished_name[1024];
5680   char      **modvalues;
5681   char      *mitMoiraId_v[] = {NULL, NULL};
5682   LDAPMod   *mods[20];
5683   LK_ENTRY  *group_base;
5684   int       group_count;
5685   int       rc;
5686   int       i;
5687   int       n;
5688   ULONG     ulongValue;
5689
5690   if (!check_string(user_name))
5691     {
5692       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", 
5693               user_name);
5694       return(AD_INVALID_NAME);
5695     }
5696
5697   group_count = 0;
5698   group_base = NULL;
5699
5700   if (strlen(MoiraId) != 0)
5701     {
5702       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
5703       attr_array[0] = "UserAccountControl";
5704       attr_array[1] = NULL;
5705       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
5706                                &group_base, &group_count, 
5707                                LDAP_SCOPE_SUBTREE)) != 0)
5708         {
5709           com_err(whoami, 0, "Unable to process user %s : %s",
5710                   user_name, ldap_err2string(rc));
5711           return(rc);
5712         }
5713     }
5714
5715   if (group_count != 1)
5716     {
5717       linklist_free(group_base);
5718       group_count = 0;
5719       group_base = NULL;
5720       sprintf(filter, "(sAMAccountName=%s)", user_name);
5721       attr_array[0] = "UserAccountControl";
5722       attr_array[1] = NULL;
5723       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
5724                                &group_base, &group_count, 
5725                                LDAP_SCOPE_SUBTREE)) != 0)
5726         {
5727           com_err(whoami, 0, "Unable to process user %s : %s",
5728                   user_name, ldap_err2string(rc));
5729           return(rc);
5730         }
5731     }
5732   
5733   if (group_count != 1)
5734     {
5735       linklist_free(group_base);
5736       com_err(whoami, 0, "Unable to find user %s in directory",
5737               user_name);
5738       return(LDAP_NO_SUCH_OBJECT);
5739     }
5740
5741   strcpy(distinguished_name, group_base->dn);
5742   ulongValue = atoi((*group_base).value);
5743
5744   if (operation == MEMBER_DEACTIVATE)
5745     ulongValue |= UF_ACCOUNTDISABLE;
5746   else    
5747     ulongValue &= ~UF_ACCOUNTDISABLE;
5748
5749   sprintf(temp, "%ld", ulongValue);
5750
5751   if ((rc = construct_newvalues(group_base, group_count, (*group_base).value, 
5752                                 temp, &modvalues, REPLACE)) == 1)
5753     goto cleanup;
5754
5755   linklist_free(group_base);
5756   group_base = NULL;
5757   group_count = 0;
5758   n = 0;
5759   ADD_ATTR("UserAccountControl", modvalues, LDAP_MOD_REPLACE);
5760
5761   if (strlen(MoiraId) != 0)
5762     {
5763     mitMoiraId_v[0] = MoiraId;
5764     ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
5765     }
5766
5767   mods[n] = NULL;
5768   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
5769
5770   for (i = 0; i < n; i++)
5771     free(mods[i]);
5772
5773   free_values(modvalues);
5774
5775   if (rc != LDAP_SUCCESS)
5776     {
5777       com_err(whoami, 0, "Unable to change status of user %s : %s",
5778               user_name, ldap_err2string(rc));
5779     }
5780   
5781  cleanup:
5782   return(rc);
5783 }
5784
5785 int user_delete(LDAP *ldap_handle, char *dn_path, 
5786                 char *u_name, char *MoiraId)
5787 {
5788   char      filter[128];
5789   char      *attr_array[3];
5790   char      distinguished_name[1024];
5791   char      user_name[512];
5792   LK_ENTRY  *group_base;
5793   int       group_count;
5794   int       rc;
5795   char      temp[256];
5796
5797   if (!check_string(u_name))
5798     return(AD_INVALID_NAME);
5799
5800   strcpy(user_name, u_name);
5801   group_count = 0;
5802   group_base = NULL;
5803
5804   if (strlen(MoiraId) != 0)
5805     {
5806       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
5807       attr_array[0] = "name";
5808       attr_array[1] = NULL;
5809       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
5810                                &group_base, &group_count, 
5811                                LDAP_SCOPE_SUBTREE)) != 0)
5812         {
5813           com_err(whoami, 0, "Unable to process user %s : %s",
5814                   user_name, ldap_err2string(rc));
5815           goto cleanup;
5816         }
5817     }
5818   
5819   if (group_count != 1)
5820     {
5821       linklist_free(group_base);
5822       group_count = 0;
5823       group_base = NULL;
5824       sprintf(filter, "(sAMAccountName=%s)", user_name);
5825       attr_array[0] = "name";
5826       attr_array[1] = NULL;
5827       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
5828                                &group_base, &group_count, 
5829                                LDAP_SCOPE_SUBTREE)) != 0)
5830         {
5831           com_err(whoami, 0, "Unable to process user %s : %s",
5832                   user_name, ldap_err2string(rc));
5833           goto cleanup;
5834         }
5835     }
5836
5837   if (group_count != 1)
5838     {
5839       goto cleanup;
5840     }
5841   
5842   strcpy(distinguished_name, group_base->dn);
5843
5844   if (rc = ldap_delete_s(ldap_handle, distinguished_name))
5845     {
5846       com_err(whoami, 0, "Unable to process user %s : %s",
5847               user_name, ldap_err2string(rc));
5848     }
5849
5850   /* Need to add code to delete mit.edu contact */
5851
5852   if (Exchange)
5853     {
5854       sprintf(temp, "cn=%s@exchange-forwarding.mit.edu,%s,%s", user_name, 
5855               contact_ou, dn_path);
5856
5857       if(rc = ldap_delete_s(ldap_handle, temp))
5858         {
5859           com_err(whoami, 0, "Unable to delete user contact for %s",
5860                   user_name);
5861         }
5862     }
5863
5864  cleanup:
5865   linklist_free(group_base);
5866
5867   return(0);
5868 }
5869
5870 void linklist_free(LK_ENTRY *linklist_base)
5871 {
5872   LK_ENTRY *linklist_previous;
5873
5874   while (linklist_base != NULL)
5875     {
5876       if (linklist_base->dn != NULL)
5877         free(linklist_base->dn);
5878
5879       if (linklist_base->attribute != NULL)
5880         free(linklist_base->attribute);
5881
5882       if (linklist_base->value != NULL)
5883         free(linklist_base->value);
5884
5885       if (linklist_base->member != NULL)
5886         free(linklist_base->member);
5887
5888       if (linklist_base->type != NULL)
5889         free(linklist_base->type);
5890
5891       if (linklist_base->list != NULL)
5892         free(linklist_base->list);
5893
5894       linklist_previous = linklist_base;
5895       linklist_base = linklist_previous->next;
5896       free(linklist_previous);
5897     }
5898 }
5899
5900 void free_values(char **modvalues)
5901 {
5902   int i;
5903
5904   i = 0;
5905
5906   if (modvalues != NULL)
5907     {
5908     while (modvalues[i] != NULL)
5909       {
5910         free(modvalues[i]);
5911         modvalues[i] = NULL;
5912         ++i;
5913       }
5914     free(modvalues);
5915   }
5916 }
5917
5918 static int illegalchars[] = {
5919   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
5920   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
5921   1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, /* SPACE - / */
5922   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 0 - ? */
5923   0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
5924   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* P - _ */
5925   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
5926   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
5927   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5928   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5929   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5930   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5931   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
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 };
5936
5937 static int illegalchars_ldap[] = {
5938   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
5939   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
5940   0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, /* SPACE - / */
5941   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, /* 0 - ? */
5942   0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
5943   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, /* P - _ */
5944   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
5945   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
5946   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5947   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5948   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5949   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5950   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5951   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5952   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5953   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5954 };
5955
5956 int check_string(char *s)
5957 {
5958   char  character;
5959   char  *string;
5960
5961   string = s;
5962
5963   for (; *s; s++)
5964     {
5965       character = *s;
5966
5967       if (isupper(character))
5968         character = tolower(character);
5969
5970       if(ActiveDirectory)
5971         {
5972           if (illegalchars[(unsigned) character])
5973             {
5974               com_err(whoami, 0, "Found illegal char '%c' (%d) in string %s",
5975                       character, (unsigned) character, string);
5976               return 0;
5977             }
5978         }
5979       else
5980         {
5981           if (illegalchars_ldap[(unsigned) character])
5982             {
5983               com_err(whoami, 0, "Found illegal char '%c' (%d) in string %s",
5984                       character, (unsigned) character, string);
5985               return 0;
5986             }
5987         }
5988     }
5989
5990   return(1);
5991 }
5992
5993 int check_container_name(char *s)
5994 {
5995   char  character;
5996
5997   for (; *s; s++)
5998     {
5999       character = *s;
6000
6001       if (isupper(character))
6002         character = tolower(character);
6003
6004       if (character == ' ')
6005         continue;
6006
6007       if (illegalchars[(unsigned) character])
6008         return 0;
6009     }
6010
6011   return(1);
6012 }
6013
6014 int mr_connect_cl(char *server, char *client, int version, int auth)
6015 {
6016   int   status;
6017   char  *motd;
6018   char  temp[128];
6019
6020   status = mr_connect(server);
6021
6022   if (status)
6023     {
6024       com_err(whoami, status, "while connecting to Moira");
6025       return status;
6026     }
6027
6028   status = mr_motd(&motd);
6029
6030   if (status)
6031     {
6032       mr_disconnect();
6033       com_err(whoami, status, "while checking server status");
6034       return status;
6035     }
6036
6037   if (motd)
6038     {
6039       sprintf(temp, "The Moira server is currently unavailable: %s", motd);
6040       com_err(whoami, status, temp);
6041       mr_disconnect();
6042       return status;
6043     }
6044
6045   status = mr_version(version);
6046
6047   if (status)
6048     {
6049       if (status == MR_UNKNOWN_PROC)
6050         {
6051           if (version > 2)
6052             status = MR_VERSION_HIGH;
6053           else
6054             status = MR_SUCCESS;
6055         }
6056
6057       if (status == MR_VERSION_HIGH)
6058         {
6059           com_err(whoami, 0, "Warning: This client is running newer code "
6060                   "than the server.");
6061                   com_err(whoami, 0, "Some operations may not work.");
6062         }
6063       else if (status && status != MR_VERSION_LOW)
6064         {
6065           com_err(whoami, status, "while setting query version number.");
6066           mr_disconnect();
6067           return status;
6068         }
6069     }
6070
6071   if (auth)
6072     {
6073       status = mr_krb5_auth(client);
6074       if (status)
6075         {
6076           com_err(whoami, status, "while authenticating to Moira.");
6077           mr_disconnect();
6078           return status;
6079         }
6080     }
6081   
6082   return MR_SUCCESS;
6083 }
6084
6085 void AfsToWinAfs(char* path, char* winPath)
6086 {
6087   char* pathPtr;
6088   char* winPathPtr;
6089   strcpy(winPath, WINAFS);
6090   pathPtr = path + strlen(AFS);
6091   winPathPtr = winPath + strlen(WINAFS);
6092   
6093   while (*pathPtr)
6094     {
6095       if (*pathPtr == '/')
6096         *winPathPtr = '\\';
6097       else
6098         *winPathPtr = *pathPtr;
6099       
6100       pathPtr++;
6101       winPathPtr++;
6102     }
6103 }
6104
6105 int GetAceInfo(int ac, char **av, void *ptr)
6106 {
6107   char **call_args;
6108   int   security_flag;
6109
6110   call_args = ptr;
6111   
6112   strcpy(call_args[0], av[L_ACE_TYPE]);
6113   strcpy(call_args[1], av[L_ACE_NAME]);
6114   security_flag = 0;
6115   get_group_membership(call_args[2], call_args[3], &security_flag, av);
6116   return(LDAP_SUCCESS);  
6117 }
6118
6119 int checkADname(LDAP *ldap_handle, char *dn_path, char *Name)
6120 {
6121   char filter[128];
6122   char *attr_array[3];
6123   int  group_count;
6124   int  rc;
6125   LK_ENTRY  *group_base;
6126   
6127   group_count = 0;
6128   group_base = NULL;
6129   
6130   sprintf(filter, "(sAMAccountName=%s)", Name);
6131   attr_array[0] = "sAMAccountName";
6132   attr_array[1] = NULL;
6133
6134   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6135                            &group_base, &group_count, 
6136                            LDAP_SCOPE_SUBTREE)) != 0)
6137     {
6138       com_err(whoami, 0, "Unable to process ACE name %s : %s",
6139               Name, ldap_err2string(rc));
6140       return(1);
6141     }
6142
6143   linklist_free(group_base);
6144   group_base = NULL;
6145
6146   if (group_count == 0)
6147     return(0);
6148   
6149   return(1);
6150 }
6151
6152 #define MAX_ACE 7
6153
6154 int ProcessAce(LDAP *ldap_handle, char *dn_path, char *Name, char *Type, 
6155                int UpdateGroup, int *ProcessGroup, char *maillist,
6156                char *nfsgroup)
6157 {
6158   char  *av[2];
6159   char  GroupName[256];
6160   char  *call_args[7];
6161   int   rc;
6162   char  *AceInfo[4];
6163   char  AceType[32];
6164   char  AceName[128];
6165   char  AceMembership[2];
6166   char  AceOu[256];
6167   char  temp[128];
6168   char  *save_argv[U_END];
6169
6170   if (!SetGroupAce)
6171     {
6172       com_err(whoami, 0, "ProcessAce disabled, skipping");
6173       return(0);
6174     }
6175
6176   strcpy(GroupName, Name);
6177   
6178   if (strcasecmp(Type, "LIST"))
6179     return(1);
6180
6181   while (1)
6182     {
6183       av[0] = GroupName;
6184       AceInfo[0] = AceType;
6185       AceInfo[1] = AceName;
6186       AceInfo[2] = AceMembership;
6187       AceInfo[3] = AceOu;
6188       memset(AceType, '\0', sizeof(AceType));
6189       memset(AceName, '\0', sizeof(AceName));
6190       memset(AceMembership, '\0', sizeof(AceMembership));
6191       memset(AceOu, '\0', sizeof(AceOu));
6192       callback_rc = 0;
6193     
6194       if (rc = mr_query("get_list_info", 1, av, GetAceInfo, AceInfo))
6195         { 
6196           if(rc != MR_NO_MATCH)
6197             com_err(whoami, 0, "Unable to get ACE info for list %s : %s", 
6198                     GroupName, error_message(rc));
6199
6200           return(1);
6201         }
6202
6203       if (callback_rc)
6204         {
6205           com_err(whoami, 0, "Unable to get ACE info for list %s", GroupName);
6206           return(1);
6207         }
6208
6209       if ((strcasecmp(AceType, "USER")) && (strcasecmp(AceType, "LIST")))
6210         return(0);
6211
6212       strcpy(temp, AceName);
6213
6214       if (!strcasecmp(AceType, "LIST"))
6215         sprintf(temp, "%s%s", AceName, group_suffix);
6216
6217       if (!UpdateGroup)
6218         {
6219           if (checkADname(ldap_handle, dn_path, temp))
6220               return(0);
6221
6222           (*ProcessGroup) = 1;
6223         }
6224
6225       if (!strcasecmp(AceInfo[0], "LIST"))
6226         {
6227           if (make_new_group(ldap_handle, dn_path, "", AceName, AceOu, 
6228                              AceMembership, 0, UpdateGroup, maillist,
6229                              nfsgroup))
6230             return(1);
6231
6232           populate_group(ldap_handle, dn_path, AceName, AceOu, AceMembership,
6233                          0, "", 1);
6234         }
6235       else if (!strcasecmp(AceInfo[0], "USER"))
6236         {
6237           av[0] = AceName;
6238           call_args[0] = (char *)ldap_handle;
6239           call_args[1] = dn_path;
6240           call_args[2] = "";
6241           call_args[3] = NULL;
6242           callback_rc = 0;
6243
6244           if(!strcasecmp(AceName, PRODUCTION_PRINCIPAL) ||
6245              !strcasecmp(AceName, TEST_PRINCIPAL))
6246             {
6247               return(1);
6248             }
6249
6250           if (rc = mr_query("get_user_account_by_login", 1, av, 
6251                             save_query_info, save_argv))
6252             {
6253               com_err(whoami, 0, "Unable to process user ACE %s for group %s.",
6254                       AceName, Name);
6255               return(1);
6256             }
6257
6258           if (rc = user_create(U_END, save_argv, call_args)) 
6259             {
6260               com_err(whoami, 0, "Unable to process user ACE %s for group %s.",
6261                       AceName, Name);
6262               return(1);
6263             }
6264           
6265           if (callback_rc)
6266             {
6267               com_err(whoami, 0, "Unable to process user Ace %s for group %s",
6268                       AceName, Name);
6269               return(1);
6270             }
6271
6272           return(0);
6273         }
6274       else
6275         return(1);
6276
6277       if (!strcasecmp(AceType, "LIST"))
6278         {
6279           if (!strcasecmp(GroupName, AceName))
6280             return(0);
6281         }
6282
6283       strcpy(GroupName, AceName);
6284     }
6285   
6286   return(1);
6287 }
6288
6289 int make_new_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
6290                    char *group_name, char *group_ou, char *group_membership, 
6291                    int group_security_flag, int updateGroup, char *maillist,
6292                    char *nfsgroup)
6293 {
6294   char  *av[3];
6295   char  *call_args[8];
6296   int   rc;
6297   LK_ENTRY  *group_base;
6298   int  group_count;
6299   char filter[128];
6300   char *attr_array[3];
6301
6302   av[0] = group_name;
6303   call_args[0] = (char *)ldap_handle;
6304   call_args[1] = dn_path;
6305   call_args[2] = group_name;
6306   call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
6307   call_args[4] = (char *)updateGroup;
6308   call_args[5] = MoiraId;
6309   call_args[6] = "0";
6310   call_args[7] = NULL;
6311   callback_rc = 0;
6312
6313   group_count = 0;
6314   group_base = NULL;
6315
6316   if (rc = mr_query("get_list_info", 1, av, group_create, call_args))
6317     {
6318       moira_disconnect();
6319       com_err(whoami, 0, "Unable to create list %s : %s", group_name, 
6320               error_message(rc));
6321       return(rc);
6322     }
6323
6324   if (callback_rc)
6325     {
6326       moira_disconnect();
6327       com_err(whoami, 0, "Unable to create list %s", group_name);
6328       return(callback_rc);
6329     }
6330
6331   return(0);
6332 }
6333
6334 int populate_group(LDAP *ldap_handle, char *dn_path, char *group_name, 
6335                    char *group_ou, char *group_membership, 
6336                    int group_security_flag, char *MoiraId, 
6337                    int synchronize)
6338 {
6339   char      *av[3];
6340   char      *call_args[7];
6341   char      *pUserOu;
6342   LK_ENTRY  *ptr;
6343   int       rc;
6344   char      member[512];
6345   char      *s;
6346   char      **members;
6347   int       i = 0;
6348   int       j = 0;
6349   int       n = 0;
6350   char      group_dn[512];
6351   LDAPMod   *mods[20];
6352   char      *member_v[] = {NULL, NULL};
6353   char      *save_argv[U_END];
6354   char      machine_ou[256];
6355   char      NewMachineName[1024];
6356
6357   com_err(whoami, 0, "Populating group %s", group_name);
6358   av[0] = group_name;
6359   call_args[0] = (char *)ldap_handle;
6360   call_args[1] = dn_path;
6361   call_args[2] = group_name;
6362   call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS | 
6363                           MOIRA_MACHINE);
6364   call_args[4] = NULL;
6365   member_base = NULL;
6366   group_members = 0;
6367
6368   if (rc = mr_query("get_end_members_of_list", 1, av,
6369                     member_list_build, call_args))
6370     {
6371       if(rc == MR_LIST)
6372         return(0);
6373       
6374       com_err(whoami, 0, "Unable to populate list %s : %s", 
6375               group_name, error_message(rc));
6376       return(3);
6377     }
6378
6379   if (member_base != NULL)
6380     {
6381       ptr = member_base;
6382
6383       while(ptr != NULL)
6384         {
6385           if (!strcasecmp(ptr->type, "LIST"))
6386             {
6387               ptr = ptr->next;
6388               continue;
6389             }
6390
6391           if (!strcasecmp(ptr->type, "MACHINE") && !ProcessMachineContainer)
6392             {
6393               ptr = ptr->next;
6394               continue;
6395             }
6396
6397           if(!strcasecmp(ptr->type, "USER"))
6398             {
6399               if(!strcasecmp(ptr->member, PRODUCTION_PRINCIPAL) ||
6400                  !strcasecmp(ptr->member, TEST_PRINCIPAL))
6401                 {
6402                   ptr = ptr->next;
6403                   continue;
6404                 }
6405             }
6406
6407           ptr = ptr->next;
6408           group_members++;
6409         }
6410     }
6411
6412   if(max_group_members && !synchronize && (group_members > max_group_members))
6413     {
6414       com_err(whoami, 0, 
6415               "Group %s membership of %d exceeds maximum %d, skipping",
6416               group_name, group_members, max_group_members);
6417       return(0);
6418     }
6419
6420   members = (char **)malloc(sizeof(char *) * 2);
6421
6422   if (member_base != NULL)
6423     {
6424       ptr = member_base;
6425
6426       while (ptr != NULL)
6427         {
6428           if (!strcasecmp(ptr->type, "LIST"))
6429             {
6430               ptr = ptr->next;
6431               continue;
6432             }
6433           
6434           if (!strcasecmp(ptr->type, "MACHINE") && !ProcessMachineContainer)
6435             {
6436               ptr = ptr->next;
6437               continue;
6438             }
6439             
6440           if(!strcasecmp(ptr->type, "USER"))
6441             {
6442               if(!strcasecmp(ptr->member, PRODUCTION_PRINCIPAL) ||
6443                  !strcasecmp(ptr->member, TEST_PRINCIPAL))
6444                 {
6445                   ptr = ptr->next;
6446                   continue;
6447                 }
6448
6449               if ((rc = check_user(ldap_handle, dn_path, ptr->member,
6450                                    "")) == AD_NO_USER_FOUND)
6451                 {
6452                   com_err(whoami, 0, "creating user %s", ptr->member);
6453
6454                   av[0] = ptr->member;
6455                   call_args[0] = (char *)ldap_handle;
6456                   call_args[1] = dn_path;
6457                   call_args[2] = "";
6458                   call_args[3] = NULL;
6459                   callback_rc = 0;
6460                   
6461                   if (rc = mr_query("get_user_account_by_login", 1, av, 
6462                                     save_query_info, save_argv))
6463                     {
6464                       com_err(whoami, 0, "Unable to create user %s " 
6465                               "while populating group %s.", ptr->member,
6466                               group_name);
6467
6468                       return(3);
6469                     }
6470
6471                   if (rc = user_create(U_END, save_argv, call_args)) 
6472                     {
6473                       com_err(whoami, 0, "Unable to create user %s "
6474                               "while populating group %s.", ptr->member,
6475                               group_name);
6476                       
6477                       return(3);
6478                     }
6479           
6480                   if (callback_rc)
6481                     {
6482                       com_err(whoami, 0, "Unable to create user %s "
6483                               "while populating group %s", ptr->member, 
6484                               group_name);
6485
6486                       return(3);
6487                     }
6488                 }
6489
6490               pUserOu = user_ou;
6491                   
6492               if(ActiveDirectory) 
6493                 {
6494                   sprintf(member, "cn=%s,%s,%s", ptr->member, pUserOu, 
6495                           dn_path);
6496                 }
6497               else 
6498                 {
6499                   sprintf(member, "uid=%s,%s,%s", ptr->member, pUserOu, 
6500                           dn_path);
6501                 }
6502             }
6503           else if (!strcasecmp(ptr->type, "STRING"))
6504             {
6505               if (contact_create(ldap_handle, dn_path, ptr->member,
6506                                  contact_ou))
6507                 return(3);
6508
6509               pUserOu = contact_ou;
6510               sprintf(member, "cn=%s,%s,%s", escape_string(ptr->member), 
6511                       pUserOu, dn_path);
6512             }
6513           else if (!strcasecmp(ptr->type, "KERBEROS"))
6514             {
6515               if (contact_create(ldap_handle, dn_path, ptr->member, 
6516                                  kerberos_ou))
6517                 return(3);
6518
6519               pUserOu = kerberos_ou;
6520               sprintf(member, "cn=%s,%s,%s", escape_string(ptr->member), 
6521                       pUserOu, dn_path);
6522             }
6523           else if (!strcasecmp(ptr->type, "MACHINE"))
6524             {
6525               memset(machine_ou, '\0', sizeof(machine_ou));
6526               memset(NewMachineName, '\0', sizeof(NewMachineName));
6527
6528               if (!get_machine_ou(ldap_handle, dn_path, ptr->member,
6529                                  machine_ou, NewMachineName))
6530                 {
6531                   pUserOu = machine_ou;
6532                   sprintf(member, "cn=%s,%s,%s", NewMachineName, pUserOu,
6533                           dn_path);
6534                 }
6535               else
6536                 {
6537                   ptr = ptr->next;                  
6538                   continue;
6539                 }
6540             }
6541
6542           if(i > 1) 
6543             members = (char **)realloc(members, ((i + 2) * sizeof(char *)));
6544           members[i++] = strdup(member);
6545
6546           ptr = ptr->next;
6547         }
6548     
6549       linklist_free(member_base);
6550       member_base = NULL;
6551     }
6552
6553   members[i] = NULL;
6554
6555   sprintf(group_dn, "cn=%s,%s,%s", group_name, group_ou, dn_path);
6556
6557   if(GroupPopulateDelete)
6558     {
6559       n = 0;
6560       ADD_ATTR("member", member_v, LDAP_MOD_REPLACE);
6561       mods[n] = NULL;
6562       
6563       if ((rc = ldap_modify_s(ldap_handle, group_dn, 
6564                               mods)) != LDAP_SUCCESS)
6565         {
6566           com_err(whoami, 0,
6567                   "Unable to populate group membership for %s: %s",
6568                   group_dn, ldap_err2string(rc));
6569         }
6570   
6571       for (i = 0; i < n; i++)
6572         free(mods[i]);
6573     }
6574
6575   n = 0;
6576   ADD_ATTR("member", members, LDAP_MOD_REPLACE);
6577   mods[n] = NULL;
6578
6579   if ((rc = ldap_modify_s(ldap_handle, group_dn, 
6580                           mods)) != LDAP_SUCCESS)
6581     {
6582       com_err(whoami, 0,
6583               "Unable to populate group membership for %s: %s",
6584               group_dn, ldap_err2string(rc));
6585     }
6586   
6587   for (i = 0; i < n; i++)
6588     free(mods[i]);
6589     
6590   free(members);
6591
6592   return(0);
6593 }
6594
6595 int process_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
6596                   char *group_name, char *group_ou, char *group_membership, 
6597                   int group_security_flag, int type, char *maillist, 
6598                   char *nfsgroup)
6599 {
6600   char      before_desc[512];
6601   char      before_name[256];
6602   char      before_group_ou[256];
6603   char      before_group_membership[2];
6604   char      distinguishedName[256];
6605   char      ad_distinguishedName[256];
6606   char      filter[128];
6607   char      *attr_array[3];
6608   int       before_security_flag;
6609   int       group_count;
6610   int       rc;
6611   LK_ENTRY  *group_base;
6612   LK_ENTRY  *ptr;
6613   char      ou_both[512];
6614   char      ou_security[512];
6615   char      ou_distribution[512];
6616   char      ou_neither[512];
6617   char      group_dn[512];
6618
6619   memset(ad_distinguishedName, '\0', sizeof(ad_distinguishedName));
6620   sprintf(distinguishedName, "CN=%s,%s,%s", group_name, group_ou, dn_path);
6621
6622   memset(filter, '\0', sizeof(filter));
6623   group_base = NULL;
6624   group_count = 0;
6625
6626   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
6627                         "*", MoiraId, 
6628                         "samAccountName", &group_base, 
6629                         &group_count, filter))
6630     return(rc);
6631
6632   if (type == CHECK_GROUPS)
6633     {
6634       if (group_count == 1)
6635         {
6636           strcpy(group_dn, group_base->dn);
6637
6638           if (!strcasecmp(group_dn, distinguishedName))
6639             {
6640               linklist_free(group_base);
6641               return(0);
6642             }
6643         }
6644
6645       linklist_free(group_base);
6646
6647       if (group_count == 0)
6648         return(AD_NO_GROUPS_FOUND);
6649
6650       if (group_count == 1)
6651         return(AD_WRONG_GROUP_DN_FOUND);
6652
6653       return(AD_MULTIPLE_GROUPS_FOUND);
6654     }
6655
6656   if (group_count == 0)
6657     {
6658       return(AD_NO_GROUPS_FOUND);
6659     }
6660
6661   if (group_count > 1)
6662     {
6663       ptr = group_base;
6664
6665       strcpy(group_dn, ptr->dn);
6666
6667       while (ptr != NULL)
6668         {
6669           if (!strcasecmp(group_dn, ptr->value))
6670             break;
6671
6672           ptr = ptr->next;
6673         }
6674
6675       if (ptr == NULL)
6676         {
6677           com_err(whoami, 0, "%d groups with moira id = %s", group_count, 
6678                   MoiraId);
6679           ptr = group_base;
6680
6681           while (ptr != NULL)
6682             {
6683               com_err(whoami, 0, "%s with moira id = %s", ptr->value, MoiraId);
6684               ptr = ptr->next;
6685             }
6686
6687           linklist_free(group_base);
6688           return(AD_MULTIPLE_GROUPS_FOUND);
6689         }
6690
6691       ptr = group_base;
6692
6693       while (ptr != NULL)
6694         {
6695           strcpy(group_dn, ptr->dn);
6696
6697           if (strcasecmp(group_dn, ptr->value))
6698             rc = ldap_delete_s(ldap_handle, ptr->value);
6699
6700           ptr = ptr->next;
6701         }
6702
6703       linklist_free(group_base);
6704       memset(filter, '\0', sizeof(filter));
6705       group_base = NULL;
6706       group_count = 0;
6707
6708       if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
6709                             "*", MoiraId, 
6710                             "samAccountName", &group_base, 
6711                             &group_count, filter))
6712         return(rc);
6713
6714       if (group_count == 0)
6715         return(AD_NO_GROUPS_FOUND);
6716
6717       if (group_count > 1)
6718         return(AD_MULTIPLE_GROUPS_FOUND);
6719     }
6720
6721   strcpy(ad_distinguishedName, group_base->dn);
6722   linklist_free(group_base);
6723   group_base = NULL;
6724   group_count = 0;
6725
6726   attr_array[0] = "sAMAccountName";
6727   attr_array[1] = NULL;
6728   
6729   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6730                            &group_base, &group_count, 
6731                            LDAP_SCOPE_SUBTREE)) != 0)
6732     {
6733       com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6734               MoiraId, ldap_err2string(rc));
6735       return(rc);
6736     }
6737   
6738   sprintf(filter, "(sAMAccountName=%s)", group_base->value);
6739
6740   if (!strcasecmp(ad_distinguishedName, distinguishedName))
6741     {
6742       linklist_free(group_base);
6743       group_base = NULL;
6744       group_count = 0;
6745       return(0);
6746     }
6747
6748   linklist_free(group_base);
6749   group_base = NULL;
6750   group_count = 0;
6751   memset(ou_both, '\0', sizeof(ou_both));
6752   memset(ou_security, '\0', sizeof(ou_security));
6753   memset(ou_distribution, '\0', sizeof(ou_distribution));
6754   memset(ou_neither, '\0', sizeof(ou_neither));
6755   memset(before_name, '\0', sizeof(before_name));
6756   memset(before_desc, '\0', sizeof(before_desc));
6757   memset(before_group_membership, '\0', sizeof(before_group_membership));
6758   
6759   attr_array[0] = "name";
6760   attr_array[1] = NULL;
6761
6762   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6763                            &group_base, &group_count, 
6764                            LDAP_SCOPE_SUBTREE)) != 0)
6765     {
6766       com_err(whoami, 0, "Unable to get list name with MoiraId = %s: %s",
6767               MoiraId, ldap_err2string(rc));
6768       return(rc);
6769     }
6770
6771   strcpy(before_name, group_base->value);
6772   linklist_free(group_base);
6773   group_base = NULL;
6774   group_count = 0;
6775
6776   attr_array[0] = "description";
6777   attr_array[1] = NULL;
6778   
6779   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6780                            &group_base, &group_count, 
6781                            LDAP_SCOPE_SUBTREE)) != 0)
6782     {
6783       com_err(whoami, 0, 
6784               "Unable to get list description with MoiraId = %s: %s",
6785               MoiraId, ldap_err2string(rc));
6786       return(rc);
6787     }
6788
6789   if (group_count != 0)
6790     {
6791       strcpy(before_desc, group_base->value);
6792       linklist_free(group_base);
6793       group_base = NULL;
6794       group_count = 0;
6795     }
6796  
6797   change_to_lower_case(ad_distinguishedName);  
6798   strcpy(ou_both, group_ou_both);
6799   change_to_lower_case(ou_both);
6800   strcpy(ou_security, group_ou_security);
6801   change_to_lower_case(ou_security);
6802   strcpy(ou_distribution, group_ou_distribution);
6803   change_to_lower_case(ou_distribution);
6804   strcpy(ou_neither, group_ou_neither);
6805   change_to_lower_case(ou_neither);
6806
6807   if (strstr(ad_distinguishedName, ou_both))
6808     {
6809       strcpy(before_group_ou, group_ou_both);
6810       before_group_membership[0] = 'B';
6811       before_security_flag = 1;
6812     }
6813   else if (strstr(ad_distinguishedName, ou_security))
6814     {
6815       strcpy(before_group_ou, group_ou_security);
6816       before_group_membership[0] = 'S';
6817       before_security_flag = 1;
6818     }
6819   else if (strstr(ad_distinguishedName, ou_distribution))
6820     {
6821       strcpy(before_group_ou, group_ou_distribution);
6822       before_group_membership[0] = 'D';
6823       before_security_flag = 0;
6824     }
6825   else if (strstr(ad_distinguishedName, ou_neither))
6826     {
6827       strcpy(before_group_ou, group_ou_neither);
6828       before_group_membership[0] = 'N';
6829       before_security_flag = 0;
6830     }
6831   else
6832     return(AD_NO_OU_FOUND);
6833
6834   rc = group_rename(ldap_handle, dn_path, before_name, 
6835                     before_group_membership, 
6836                     before_group_ou, before_security_flag, before_desc,
6837                     group_name, group_membership, group_ou, 
6838                     group_security_flag,
6839                     before_desc, MoiraId, filter, maillist, nfsgroup);
6840
6841   return(rc);
6842 }
6843
6844 void change_to_lower_case(char *ptr)
6845 {
6846   int i;
6847
6848   for (i = 0; i < (int)strlen(ptr); i++)
6849     {
6850       ptr[i] = tolower(ptr[i]);
6851     }
6852 }
6853
6854 int ad_get_group(LDAP *ldap_handle, char *dn_path, 
6855                  char *group_name, char *group_membership, 
6856                  char *MoiraId, char *attribute,
6857                  LK_ENTRY **linklist_base, int *linklist_count,
6858                  char *rFilter)
6859 {
6860   LK_ENTRY  *pPtr;
6861   char  filter[128];
6862   char  *attr_array[3];
6863   char  *dn;
6864   int   rc;
6865
6866   (*linklist_base) = NULL;
6867   (*linklist_count) = 0;
6868
6869   if (strlen(rFilter) != 0)
6870     {
6871       strcpy(filter, rFilter);
6872       attr_array[0] = attribute;
6873       attr_array[1] = NULL;
6874       
6875       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6876                                linklist_base, linklist_count, 
6877                                LDAP_SCOPE_SUBTREE)) != 0)
6878         {
6879           com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6880                   MoiraId, ldap_err2string(rc));
6881          return(rc);
6882        }
6883
6884     if ((*linklist_count) == 1)
6885       {
6886         strcpy(rFilter, filter);
6887         return(0);
6888       }
6889     }
6890
6891   linklist_free((*linklist_base));
6892   (*linklist_base) = NULL;
6893   (*linklist_count) = 0;
6894
6895   if (strlen(MoiraId) != 0)
6896     {
6897       sprintf(filter, "(&(objectClass=group)(mitMoiraId=%s))", MoiraId);
6898
6899       attr_array[0] = attribute;
6900       attr_array[1] = NULL;
6901
6902       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6903                                linklist_base, linklist_count, 
6904                                LDAP_SCOPE_SUBTREE)) != 0)
6905         {
6906           com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6907                   MoiraId, ldap_err2string(rc));
6908          return(rc);
6909        }
6910     }
6911
6912   if ((*linklist_count) > 1)
6913     {
6914       com_err(whoami, 0, "multiple groups with mitMoiraId = %s", MoiraId);
6915       pPtr = (*linklist_base);
6916
6917       while (pPtr)
6918         {
6919           com_err(whoami, 0, "groups %s has mitMoiraId = %s", pPtr->value, 
6920                   MoiraId);
6921           pPtr = pPtr->next;
6922         }
6923
6924       linklist_free((*linklist_base));
6925       (*linklist_base) = NULL;
6926       (*linklist_count) = 0;
6927     }
6928
6929   if ((*linklist_count) == 1)
6930     {
6931
6932       pPtr = (*linklist_base);
6933       dn = strdup(pPtr->dn);
6934       dn += 3;
6935
6936       if (!memcmp(dn, group_name, strlen(group_name)))
6937         {
6938           strcpy(rFilter, filter);
6939           return(0);
6940         }
6941     }
6942
6943   linklist_free((*linklist_base));
6944   (*linklist_base) = NULL;
6945   (*linklist_count) = 0;
6946   sprintf(filter, "(sAMAccountName=%s%s)", group_name, group_suffix);
6947
6948   attr_array[0] = attribute;
6949   attr_array[1] = NULL;
6950
6951   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6952                            linklist_base, linklist_count, 
6953                            LDAP_SCOPE_SUBTREE)) != 0)
6954     {
6955       com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6956               MoiraId, ldap_err2string(rc));
6957       return(rc);
6958     }
6959
6960   if ((*linklist_count) == 1)
6961     {
6962       strcpy(rFilter, filter);
6963       return(0);
6964     }
6965
6966   return(0);
6967 }
6968
6969 int check_user(LDAP *ldap_handle, char *dn_path, char *UserName, char *MoiraId)
6970 {
6971   char filter[128];
6972   char *attr_array[3];
6973   char SamAccountName[64];
6974   int  group_count;
6975   int  rc;
6976   LK_ENTRY  *group_base;
6977   LK_ENTRY  *gPtr;
6978
6979   group_count = 0;
6980   group_base = NULL;
6981
6982   if (strlen(MoiraId) != 0)
6983     {
6984       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
6985
6986       attr_array[0] = "sAMAccountName";
6987       attr_array[1] = NULL;
6988       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6989                                &group_base, &group_count, 
6990                                LDAP_SCOPE_SUBTREE)) != 0)
6991         {
6992           com_err(whoami, 0, "Unable to process user %s : %s",
6993                   UserName, ldap_err2string(rc));
6994           return(rc);
6995         }
6996
6997       if (group_count > 1)
6998         {
6999           com_err(whoami, 0, "multiple users exist with MoiraId = %s",
7000                   MoiraId);
7001           gPtr = group_base;
7002
7003           while (gPtr)
7004             {
7005               com_err(whoami, 0, "user %s exist with MoiraId = %s",
7006                       gPtr->value, MoiraId);
7007               gPtr = gPtr->next;
7008             }
7009         }
7010     }
7011
7012   if (group_count != 1)
7013     {
7014       linklist_free(group_base);
7015       group_count = 0;
7016       group_base = NULL;
7017       sprintf(filter, "(sAMAccountName=%s)", UserName);
7018       attr_array[0] = "sAMAccountName";
7019       attr_array[1] = NULL;
7020
7021       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
7022                                &group_base, &group_count, 
7023                                LDAP_SCOPE_SUBTREE)) != 0)
7024         {
7025           com_err(whoami, 0, "Unable to process user %s : %s",
7026                   UserName, ldap_err2string(rc));
7027           return(rc);
7028         }
7029     }
7030
7031   if (group_count != 1)
7032     {
7033       linklist_free(group_base);
7034       return(AD_NO_USER_FOUND);
7035     }
7036
7037   strcpy(SamAccountName, group_base->value);
7038   linklist_free(group_base);
7039   group_count = 0;
7040   rc = 0;
7041
7042   if (strcmp(SamAccountName, UserName))
7043     {
7044       com_err(whoami, 0, 
7045               "User object %s with MoiraId %s has mismatched usernames " 
7046               "(LDAP username %s, Moira username %s)", SamAccountName,
7047               MoiraId, SamAccountName, UserName);
7048     }
7049
7050   return(0);
7051 }
7052
7053 void container_get_dn(char *src, char *dest)
7054 {
7055   char *sPtr;
7056   char *array[20];
7057   char name[256];
7058   int  n;
7059
7060   memset(array, '\0', 20 * sizeof(array[0]));
7061
7062   if (strlen(src) == 0)
7063     return;
7064
7065   strcpy(name, src);
7066   sPtr = name;
7067   n = 0;
7068   array[n] = name;
7069   ++n;
7070
7071   while (*sPtr)
7072     {
7073       if ((*sPtr) == '/')
7074         {
7075           (*sPtr) = '\0';
7076           ++sPtr;
7077           array[n] = sPtr;
7078           ++n;
7079         }
7080       else
7081         ++sPtr;
7082     }
7083
7084   strcpy(dest, "OU=");
7085
7086   while (n != 0)
7087     {
7088       strcat(dest, array[n-1]);
7089       --n;
7090       if (n > 0)
7091         {
7092           strcat(dest, ",OU=");
7093         }
7094     }
7095
7096   return;
7097 }
7098
7099 void container_get_name(char *src, char *dest)
7100 {
7101   char *sPtr;
7102   char *dPtr;
7103
7104   if (strlen(src) == 0)
7105     return;
7106
7107   sPtr = src;
7108   dPtr = src;
7109
7110   while (*sPtr)
7111     {
7112       if ((*sPtr) == '/')
7113         {
7114           dPtr = sPtr;
7115           ++dPtr;
7116         }
7117       ++sPtr;
7118     }
7119
7120   strcpy(dest, dPtr);
7121   return;
7122 }
7123
7124 void container_check(LDAP *ldap_handle, char *dn_path, char *name)
7125 {
7126   char cName[256];
7127   char *av[7];
7128   int  i;
7129   int  rc;
7130
7131   strcpy(cName, name);
7132
7133   for (i = 0; i < (int)strlen(cName); i++)
7134     {
7135       if (cName[i] == '/')
7136         {
7137           cName[i] = '\0';
7138           av[CONTAINER_NAME] = cName;
7139           av[CONTAINER_DESC] = "";
7140           av[CONTAINER_LOCATION] = "";
7141           av[CONTAINER_CONTACT] = "";
7142           av[CONTAINER_TYPE] = "";
7143           av[CONTAINER_ID] = "";
7144           av[CONTAINER_ROWID] = "";
7145           rc = container_create(ldap_handle, dn_path, 7, av);
7146
7147           if (rc == LDAP_SUCCESS)
7148             {
7149               com_err(whoami, 0, "container %s created without a mitMoiraId", 
7150                       cName);
7151             }
7152
7153           cName[i] = '/';
7154         }
7155     }
7156 }
7157
7158 int container_rename(LDAP *ldap_handle, char *dn_path, int beforec, 
7159                      char **before, int afterc, char **after)
7160 {
7161   char      dName[256];
7162   char      cName[256];
7163   char      new_cn[128];
7164   char      new_dn_path[256];
7165   char      temp[256];
7166   char      distinguishedName[256];
7167   char      *pPtr;
7168   int       rc;
7169   int       i;
7170
7171   memset(cName, '\0', sizeof(cName));
7172   container_get_name(after[CONTAINER_NAME], cName);
7173
7174   if (!check_container_name(cName))
7175     {
7176       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", 
7177               cName);
7178       return(AD_INVALID_NAME);
7179     }
7180
7181   memset(distinguishedName, '\0', sizeof(distinguishedName));
7182
7183   if (rc = container_get_distinguishedName(ldap_handle, dn_path, 
7184                                            distinguishedName, beforec, before))
7185     return(rc);
7186
7187   if (strlen(distinguishedName) == 0)
7188     {
7189       rc = container_create(ldap_handle, dn_path, afterc, after);
7190       return(rc);
7191     }
7192
7193   strcpy(temp, after[CONTAINER_NAME]);
7194   pPtr = temp;
7195
7196   for (i = 0; i < (int)strlen(temp); i++)
7197     {
7198       if (temp[i] == '/')
7199         {
7200           pPtr = &temp[i];
7201         }
7202     }
7203
7204   (*pPtr) = '\0';
7205
7206   container_get_dn(temp, dName);
7207
7208   if (strlen(temp) != 0)
7209     sprintf(new_dn_path, "%s,%s", dName, dn_path);
7210   else
7211     sprintf(new_dn_path, "%s", dn_path);
7212
7213   sprintf(new_cn, "OU=%s", cName);
7214
7215   container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
7216
7217   if ((rc = ldap_rename_s(ldap_handle, distinguishedName, new_cn, new_dn_path,
7218                           TRUE, NULL, NULL)) != LDAP_SUCCESS)
7219     {
7220       com_err(whoami, 0, "Unable to rename container from %s to %s : %s",
7221               before[CONTAINER_NAME], after[CONTAINER_NAME], 
7222               ldap_err2string(rc));
7223       return(rc);
7224     }
7225
7226   memset(dName, '\0', sizeof(dName));
7227   container_get_dn(after[CONTAINER_NAME], dName);
7228   rc = container_adupdate(ldap_handle, dn_path, dName, "", afterc, after);
7229
7230   return(rc);
7231 }
7232
7233 int container_delete(LDAP *ldap_handle, char *dn_path, int count, char **av)
7234 {
7235   char      distinguishedName[256];
7236   int       rc;
7237
7238   memset(distinguishedName, '\0', sizeof(distinguishedName));
7239
7240   if (rc = container_get_distinguishedName(ldap_handle, dn_path, 
7241                                            distinguishedName, count, av))
7242     return(rc);
7243
7244   if (strlen(distinguishedName) == 0)
7245     return(0);
7246
7247   if ((rc = ldap_delete_s(ldap_handle, distinguishedName)) != LDAP_SUCCESS)
7248     {
7249       if (rc == LDAP_NOT_ALLOWED_ON_NONLEAF)
7250         container_move_objects(ldap_handle, dn_path, distinguishedName);
7251       else
7252         com_err(whoami, 0, "Unable to delete container %s from directory : %s",
7253                 av[CONTAINER_NAME], ldap_err2string(rc));
7254     }
7255
7256   return(rc);
7257 }
7258
7259 int container_create(LDAP *ldap_handle, char *dn_path, int count, char **av)
7260 {
7261   char      *attr_array[3];
7262   LK_ENTRY  *group_base;
7263   int       group_count;
7264   LDAPMod   *mods[20];
7265   char      *objectClass_v[] = {"top", 
7266                            "organizationalUnit", 
7267                            NULL};
7268
7269   char *ou_v[] = {NULL, NULL};
7270   char *name_v[] = {NULL, NULL};
7271   char *moiraId_v[] = {NULL, NULL};
7272   char *desc_v[] = {NULL, NULL};
7273   char *managedBy_v[] = {NULL, NULL};
7274   char dName[256];
7275   char cName[256];
7276   char managedByDN[256];
7277   char filter[256];
7278   char temp[256];
7279   int  n;
7280   int  i;
7281   int  rc;
7282     
7283   memset(filter, '\0', sizeof(filter));
7284   memset(dName, '\0', sizeof(dName));
7285   memset(cName, '\0', sizeof(cName));
7286   memset(managedByDN, '\0', sizeof(managedByDN));
7287   container_get_dn(av[CONTAINER_NAME], dName);
7288   container_get_name(av[CONTAINER_NAME], cName);
7289
7290   if ((strlen(cName) == 0) || (strlen(dName) == 0))
7291     {
7292       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", 
7293               cName);
7294       return(AD_INVALID_NAME);
7295     }
7296
7297   if (!check_container_name(cName))
7298     {
7299       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", 
7300               cName);
7301       return(AD_INVALID_NAME);
7302     }
7303
7304   n = 0;
7305   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
7306   name_v[0] = cName;
7307   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
7308   ou_v[0] = cName;
7309   ADD_ATTR("ou", ou_v, LDAP_MOD_ADD);
7310
7311   if (strlen(av[CONTAINER_ROWID]) != 0)
7312     {
7313       moiraId_v[0] = av[CONTAINER_ROWID];
7314       ADD_ATTR("mitMoiraId", moiraId_v, LDAP_MOD_ADD);
7315     }
7316
7317   if (strlen(av[CONTAINER_DESC]) != 0)
7318     {
7319       desc_v[0] = av[CONTAINER_DESC];
7320       ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
7321     }
7322
7323   if ((strlen(av[CONTAINER_TYPE]) != 0) && (strlen(av[CONTAINER_ID]) != 0))
7324     {
7325       if (!strcasecmp(av[CONTAINER_TYPE], "KERBEROS"))
7326         {
7327           if (!contact_create(ldap_handle, dn_path, av[CONTAINER_ID], 
7328                               kerberos_ou))
7329             {
7330               sprintf(managedByDN, "CN=%s,%s,%s", av[CONTAINER_ID], 
7331                       kerberos_ou, dn_path);
7332               managedBy_v[0] = managedByDN;
7333               ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_ADD);
7334             }
7335         }
7336       else
7337         {
7338           if (!strcasecmp(av[CONTAINER_TYPE], "USER"))
7339             {
7340               sprintf(filter, "(&(cn=%s)(&(objectCategory=person)"
7341                       "(objectClass=user)))", av[CONTAINER_ID]);
7342             }
7343
7344           if (!strcasecmp(av[CONTAINER_TYPE], "LIST"))
7345             {
7346               sprintf(filter, "(&(objectClass=group)(cn=%s))", 
7347                       av[CONTAINER_ID]);
7348             }
7349
7350           if (strlen(filter) != 0)
7351             {
7352               attr_array[0] = "distinguishedName";
7353               attr_array[1] = NULL;
7354               group_count = 0;
7355               group_base = NULL;
7356               if ((rc = linklist_build(ldap_handle, dn_path, filter, 
7357                                        attr_array, 
7358                                        &group_base, &group_count, 
7359                                        LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7360                 {
7361                   if (group_count == 1)
7362                     {
7363                       strcpy(managedByDN, group_base->value);
7364                       managedBy_v[0] = managedByDN;
7365                       ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_ADD);
7366                     }
7367                   linklist_free(group_base);
7368                   group_base = NULL;
7369                   group_count = 0;
7370                 }
7371             }
7372         }
7373     }
7374   
7375   mods[n] = NULL;
7376
7377   sprintf(temp, "%s,%s", dName, dn_path);
7378   rc = ldap_add_ext_s(ldap_handle, temp, mods, NULL, NULL);
7379   
7380   for (i = 0; i < n; i++)
7381     free(mods[i]);
7382   
7383   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
7384     {
7385       com_err(whoami, 0, "Unable to create container %s : %s",
7386               cName, ldap_err2string(rc));
7387       return(rc);
7388     }
7389
7390   if (rc == LDAP_ALREADY_EXISTS)
7391     {
7392       if (strlen(av[CONTAINER_ROWID]) != 0)
7393         rc = container_adupdate(ldap_handle, dn_path, dName, "", count, av);
7394     }
7395
7396   return(rc);
7397 }
7398
7399 int container_update(LDAP *ldap_handle, char *dn_path, int beforec, 
7400                      char **before, int afterc, char **after)
7401 {
7402   char distinguishedName[256];
7403   int  rc;
7404
7405   memset(distinguishedName, '\0', sizeof(distinguishedName));
7406
7407   if (rc = container_get_distinguishedName(ldap_handle, dn_path, 
7408                                            distinguishedName, afterc, after))
7409     return(rc);
7410
7411   if (strlen(distinguishedName) == 0)
7412     {
7413       rc = container_create(ldap_handle, dn_path, afterc, after);
7414       return(rc);
7415     }
7416   
7417   container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
7418   rc = container_adupdate(ldap_handle, dn_path, "", distinguishedName, afterc,
7419                           after);
7420
7421   return(rc);
7422 }
7423
7424 int container_get_distinguishedName(LDAP *ldap_handle, char *dn_path, 
7425                                     char *distinguishedName, int count, 
7426                                     char **av)
7427 {
7428   char      *attr_array[3];
7429   LK_ENTRY  *group_base;
7430   int       group_count;
7431   char      dName[256];
7432   char      cName[256];
7433   char      filter[512];
7434   int       rc;
7435
7436   memset(filter, '\0', sizeof(filter));
7437   memset(dName, '\0', sizeof(dName));
7438   memset(cName, '\0', sizeof(cName));
7439   container_get_dn(av[CONTAINER_NAME], dName);
7440   container_get_name(av[CONTAINER_NAME], cName);
7441
7442   if (strlen(dName) == 0)
7443     {
7444       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", 
7445               av[CONTAINER_NAME]);
7446       return(AD_INVALID_NAME);
7447     }
7448
7449   if (!check_container_name(cName))
7450     {
7451       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", 
7452               cName);
7453       return(AD_INVALID_NAME);
7454     }
7455   
7456   sprintf(filter, "(&(objectClass=organizationalUnit)(mitMoiraId=%s))", 
7457           av[CONTAINER_ROWID]);
7458   attr_array[0] = "distinguishedName";
7459   attr_array[1] = NULL;
7460   group_count = 0;
7461   group_base = NULL;
7462
7463   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
7464                            &group_base, &group_count, 
7465                            LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7466     {
7467       if (group_count == 1)
7468         {
7469           strcpy(distinguishedName, group_base->value);
7470         }
7471
7472       linklist_free(group_base);
7473       group_base = NULL;
7474       group_count = 0;
7475     }
7476
7477   if (strlen(distinguishedName) == 0)
7478     {
7479       sprintf(filter, "(&(objectClass=organizationalUnit)"
7480               "(distinguishedName=%s,%s))", dName, dn_path);
7481       attr_array[0] = "distinguishedName";
7482       attr_array[1] = NULL;
7483       group_count = 0;
7484       group_base = NULL;
7485
7486       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
7487                                &group_base, &group_count, 
7488                                LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7489         {
7490           if (group_count == 1)
7491             {
7492               strcpy(distinguishedName, group_base->value);
7493             }
7494
7495           linklist_free(group_base);
7496           group_base = NULL;
7497           group_count = 0;
7498         }
7499     }
7500
7501   return(0);
7502 }
7503
7504 int container_adupdate(LDAP *ldap_handle, char *dn_path, char *dName, 
7505                        char *distinguishedName, int count, char **av)
7506 {
7507   char      *attr_array[5];
7508   LK_ENTRY  *group_base;
7509   LK_ENTRY  *pPtr;
7510   LDAPMod   *mods[20];
7511   int       group_count;
7512   char      filter[512];
7513   char      *moiraId_v[] = {NULL, NULL};
7514   char      *desc_v[] = {NULL, NULL};
7515   char      *managedBy_v[] = {NULL, NULL};
7516   char      managedByDN[256];
7517   char      moiraId[64];
7518   char      desc[256];
7519   char      ad_path[512];
7520   int       rc;
7521   int       i;
7522   int       n;
7523
7524
7525   strcpy(ad_path, distinguishedName);
7526
7527   if (strlen(dName) != 0)
7528     sprintf(ad_path, "%s,%s", dName, dn_path);
7529
7530   sprintf(filter, "(&(objectClass=organizationalUnit)(distinguishedName=%s))",
7531           ad_path);
7532
7533   if (strlen(av[CONTAINER_ID]) != 0)
7534     sprintf(filter, "(&(objectClass=organizationalUnit)(mitMoiraId=%s))", 
7535             av[CONTAINER_ROWID]);
7536
7537   attr_array[0] = "mitMoiraId";
7538   attr_array[1] = "description";
7539   attr_array[2] = "managedBy";
7540   attr_array[3] = NULL;
7541   group_count = 0;
7542   group_base = NULL;
7543
7544   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
7545                            &group_base, &group_count, 
7546                            LDAP_SCOPE_SUBTREE)) != LDAP_SUCCESS)
7547     {
7548       com_err(whoami, 0, "Unable to retreive container info for %s : %s",
7549               av[CONTAINER_NAME], ldap_err2string(rc));
7550       return(rc);
7551     }
7552
7553   memset(managedByDN, '\0', sizeof(managedByDN));
7554   memset(moiraId, '\0', sizeof(moiraId));
7555   memset(desc, '\0', sizeof(desc));
7556   pPtr = group_base;
7557
7558   while (pPtr)
7559     {
7560       if (!strcasecmp(pPtr->attribute, "description"))
7561         strcpy(desc, pPtr->value);
7562       else if (!strcasecmp(pPtr->attribute, "managedBy"))
7563         strcpy(managedByDN, pPtr->value);
7564       else if (!strcasecmp(pPtr->attribute, "mitMoiraId"))
7565         strcpy(moiraId, pPtr->value);
7566       pPtr = pPtr->next;
7567     }
7568
7569   linklist_free(group_base);
7570   group_base = NULL;
7571   group_count = 0;
7572
7573   n = 0;
7574   if (strlen(av[CONTAINER_ROWID]) != 0)
7575     {
7576       moiraId_v[0] = av[CONTAINER_ROWID];
7577       ADD_ATTR("mitMoiraId", moiraId_v, LDAP_MOD_REPLACE);
7578     }
7579
7580   if (strlen(av[CONTAINER_DESC]) != 0)
7581     {
7582       attribute_update(ldap_handle, ad_path, av[CONTAINER_DESC], "description",
7583                        dName);
7584     }
7585   else
7586     {
7587       if (strlen(desc) != 0)
7588         {
7589           attribute_update(ldap_handle, ad_path, "", "description", dName);
7590         }
7591     }
7592
7593   if ((strlen(av[CONTAINER_TYPE]) != 0) && (strlen(av[CONTAINER_ID]) != 0))
7594     {
7595       if (!strcasecmp(av[CONTAINER_TYPE], "KERBEROS"))
7596         {
7597           if (!contact_create(ldap_handle, dn_path, av[CONTAINER_ID], 
7598                               kerberos_ou))
7599             {
7600               sprintf(managedByDN, "CN=%s,%s,%s", av[CONTAINER_ID], 
7601                       kerberos_ou, dn_path);
7602               managedBy_v[0] = managedByDN;
7603               ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_REPLACE);
7604             }
7605           else
7606             {
7607               if (strlen(managedByDN) != 0)
7608                 {
7609                   attribute_update(ldap_handle, ad_path, "", "managedBy", 
7610                                    dName);
7611                 }
7612             }
7613         }
7614       else
7615         {
7616           memset(filter, '\0', sizeof(filter));
7617
7618           if (!strcasecmp(av[CONTAINER_TYPE], "USER"))
7619             {
7620               sprintf(filter, "(&(cn=%s)(&(objectCategory=person)"
7621                       "(objectClass=user)))", av[CONTAINER_ID]);
7622             }
7623
7624           if (!strcasecmp(av[CONTAINER_TYPE], "LIST"))
7625             {
7626               sprintf(filter, "(&(objectClass=group)(cn=%s))", 
7627                       av[CONTAINER_ID]);
7628             }
7629
7630           if (strlen(filter) != 0)
7631             {
7632               attr_array[0] = "distinguishedName";
7633               attr_array[1] = NULL;
7634               group_count = 0;
7635               group_base = NULL;
7636               if ((rc = linklist_build(ldap_handle, dn_path, filter, 
7637                                        attr_array, &group_base, &group_count, 
7638                                        LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7639                 {
7640                   if (group_count == 1)
7641                     {
7642                       strcpy(managedByDN, group_base->value);
7643                       managedBy_v[0] = managedByDN;
7644                       ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_REPLACE);
7645                     }
7646                   else
7647                     {
7648                       if (strlen(managedByDN) != 0)
7649                         {
7650                           attribute_update(ldap_handle, ad_path, "", 
7651                                            "managedBy", dName);
7652                         }
7653                     }
7654
7655                   linklist_free(group_base);
7656                   group_base = NULL;
7657                   group_count = 0;
7658                 }
7659             }
7660           else
7661             {
7662               if (strlen(managedByDN) != 0)
7663                 {
7664                   attribute_update(ldap_handle, ad_path, "", "managedBy", 
7665                                    dName);
7666                 }
7667             }
7668         }
7669     }
7670
7671   mods[n] = NULL;
7672
7673   if (n == 0)
7674     return(LDAP_SUCCESS);
7675
7676   rc = ldap_modify_s(ldap_handle, ad_path, mods);
7677
7678   for (i = 0; i < n; i++)
7679     free(mods[i]);
7680
7681   if (rc != LDAP_SUCCESS)
7682     {
7683       com_err(whoami, 0, "Unable to modify container info for %s : %s",
7684               av[CONTAINER_NAME], ldap_err2string(rc));
7685       return(rc);
7686     }
7687   
7688   return(rc);
7689 }
7690
7691 int container_move_objects(LDAP *ldap_handle, char *dn_path, char *dName)
7692 {
7693   char      *attr_array[3];
7694   LK_ENTRY  *group_base;
7695   LK_ENTRY  *pPtr;
7696   int       group_count;
7697   char      filter[512];
7698   char      new_cn[128];
7699   char      temp[256];
7700   int       rc;
7701   int       NumberOfEntries = 10;
7702   int       i;
7703   int       count;
7704
7705   rc = ldap_set_option(ldap_handle, LDAP_OPT_SIZELIMIT, &NumberOfEntries);
7706
7707   for (i = 0; i < 3; i++)
7708     {
7709       memset(filter, '\0', sizeof(filter));
7710
7711       if (i == 0)
7712         {
7713           strcpy(filter, "(!(|(objectClass=computer)"
7714                  "(objectClass=organizationalUnit)))");
7715           attr_array[0] = "cn";
7716           attr_array[1] = NULL;
7717         }
7718       else if (i == 1)
7719         {
7720           strcpy(filter, "(objectClass=computer)");
7721           attr_array[0] = "cn";
7722           attr_array[1] = NULL;
7723         }
7724       else
7725         {
7726           strcpy(filter, "(objectClass=organizationalUnit)");
7727           attr_array[0] = "ou";
7728           attr_array[1] = NULL;
7729         }
7730
7731       while (1)
7732         {
7733           if ((rc = linklist_build(ldap_handle, dName, filter, attr_array, 
7734                                    &group_base, &group_count, 
7735                                    LDAP_SCOPE_SUBTREE)) != LDAP_SUCCESS)
7736             {
7737               break;
7738             }
7739
7740           if (group_count == 0)
7741             break;
7742
7743           pPtr = group_base;
7744
7745           while(pPtr)
7746             {
7747               if (!strcasecmp(pPtr->attribute, "cn"))
7748                 {
7749                   sprintf(new_cn, "cn=%s", pPtr->value);
7750                   if (i == 0)
7751                     sprintf(temp, "%s,%s", orphans_other_ou, dn_path);
7752                   if (i == 1)
7753                     sprintf(temp, "%s,%s", orphans_machines_ou, dn_path);
7754                   count = 1;
7755
7756                   while (1)
7757                     {
7758                       rc = ldap_rename_s(ldap_handle, pPtr->dn, new_cn, temp,
7759                                          TRUE, NULL, NULL);
7760                       if (rc == LDAP_ALREADY_EXISTS)
7761                         {
7762                           sprintf(new_cn, "cn=%s_%d", pPtr->value, count);
7763                           ++count;
7764                         }
7765                       else
7766                         break;
7767                     }
7768                 }
7769               else if (!strcasecmp(pPtr->attribute, "ou"))
7770                 {
7771                   rc = ldap_delete_s(ldap_handle, pPtr->dn);
7772                 }
7773
7774               pPtr = pPtr->next;
7775             }
7776
7777           linklist_free(group_base);
7778           group_base = NULL;
7779           group_count = 0;
7780         }
7781     }
7782
7783   return(0);
7784 }
7785
7786 int get_machine_ou(LDAP *ldap_handle, char *dn_path, char *member, 
7787                    char *machine_ou, char *NewMachineName)
7788 {
7789   LK_ENTRY  *group_base;
7790   int  group_count;
7791   int  i;
7792   char filter[128];
7793   char *attr_array[3];
7794   char cn[256];
7795   char dn[256];
7796   char temp[256];
7797   char *pPtr;
7798   int   rc;
7799
7800   strcpy(NewMachineName, member);
7801   rc = moira_connect();
7802   rc = GetMachineName(NewMachineName);
7803   moira_disconnect();
7804
7805   if (strlen(NewMachineName) == 0)
7806     {
7807       com_err(whoami, 0, "Unable to find alais for machine %s in Moira", 
7808               member);
7809       return(1);
7810     }
7811
7812   pPtr = NULL;
7813   pPtr = strchr(NewMachineName, '.');
7814
7815   if (pPtr != NULL)
7816     (*pPtr) = '\0';
7817
7818   group_base = NULL;
7819   group_count = 0;
7820   sprintf(filter, "(sAMAccountName=%s$)", NewMachineName);
7821   attr_array[0] = "cn";
7822   attr_array[1] = NULL;
7823   sprintf(temp, "%s", dn_path);
7824
7825   if ((rc = linklist_build(ldap_handle, temp, filter, attr_array, 
7826                            &group_base, &group_count, 
7827                            LDAP_SCOPE_SUBTREE)) != 0)
7828     {
7829       com_err(whoami, 0, "Unable to process machine %s : %s",
7830               member, ldap_err2string(rc));
7831       return(1);
7832     }
7833
7834   if (group_count != 1)
7835     {
7836       return(1);
7837     }
7838
7839   strcpy(dn, group_base->dn);
7840   strcpy(cn, group_base->value);
7841
7842   for (i = 0; i < (int)strlen(dn); i++)
7843     dn[i] = tolower(dn[i]);
7844
7845   for (i = 0; i < (int)strlen(cn); i++)
7846     cn[i] = tolower(cn[i]);
7847
7848   linklist_free(group_base);
7849   pPtr = NULL;
7850   pPtr = strstr(dn, cn);
7851
7852   if (pPtr == NULL)
7853     {
7854       com_err(whoami, 0, "Unable to process machine %s",
7855               member);
7856       return(1);
7857     }
7858
7859   pPtr += strlen(cn) + 1;
7860   strcpy(machine_ou, pPtr);
7861   pPtr = NULL;
7862   pPtr = strstr(machine_ou, "dc=");
7863
7864   if (pPtr == NULL)
7865     {
7866       com_err(whoami, 0, "Unable to process machine %s",
7867               member);
7868       return(1);
7869     }
7870
7871   --pPtr;
7872   (*pPtr) = '\0';
7873
7874   return(0);
7875 }
7876
7877 int machine_move_to_ou(LDAP *ldap_handle, char * dn_path, 
7878                        char *MoiraMachineName, char *DestinationOu)
7879 {
7880   char        NewCn[128];
7881   char        OldDn[512];
7882   char        MachineName[128];
7883   char        filter[128];
7884   char        *attr_array[3];
7885   char        NewOu[256];
7886   char        *cPtr = NULL;
7887   int         group_count;
7888   long        rc;
7889   LK_ENTRY    *group_base;
7890
7891   group_count = 0;
7892   group_base = NULL;
7893   
7894   strcpy(MachineName, MoiraMachineName);
7895   rc = GetMachineName(MachineName);
7896
7897   if (strlen(MachineName) == 0)
7898     {
7899       com_err(whoami, 0, "Unable to find alais for machine %s in Moira", 
7900               MoiraMachineName);
7901       return(1);
7902     }
7903   
7904   cPtr = strchr(MachineName, '.');
7905
7906   if (cPtr != NULL)
7907     (*cPtr) = '\0';
7908
7909   sprintf(filter, "(sAMAccountName=%s$)", MachineName);
7910   attr_array[0] = "sAMAccountName";
7911   attr_array[1] = NULL;
7912
7913   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
7914                            &group_base, 
7915                            &group_count, LDAP_SCOPE_SUBTREE)) != 0)
7916     {
7917       com_err(whoami, 0, "Unable to process machine %s : %s",
7918               MoiraMachineName, ldap_err2string(rc));
7919       return(1);
7920     }
7921   
7922   if (group_count == 1)
7923     strcpy(OldDn, group_base->dn);
7924
7925   linklist_free(group_base);
7926   group_base = NULL;
7927
7928   if (group_count != 1)
7929     {
7930       com_err(whoami, 0, "Unable to find machine %s in directory: %s", 
7931               MoiraMachineName);
7932       return(1);
7933     }
7934
7935   sprintf(NewOu, "%s,%s", DestinationOu, dn_path);
7936   cPtr = strchr(OldDn, ',');
7937
7938   if (cPtr != NULL)
7939     {
7940       ++cPtr;
7941       if (!strcasecmp(cPtr, NewOu))
7942         return(0);
7943     }
7944
7945   sprintf(NewCn, "CN=%s", MachineName);
7946   rc = ldap_rename_s(ldap_handle, OldDn, NewCn, NewOu, TRUE, NULL, NULL);
7947
7948   return(rc);
7949 }
7950
7951 int machine_check(LDAP *ldap_handle, char *dn_path, char *machine_name)
7952 {
7953   char    Name[128];
7954   char    *pPtr;
7955   int     rc;
7956   
7957   memset(Name, '\0', sizeof(Name));
7958   strcpy(Name, machine_name);
7959   pPtr = NULL;
7960   pPtr = strchr(Name, '.');
7961
7962   if (pPtr != NULL)
7963     (*pPtr) = '\0';
7964
7965   strcat(Name, "$");
7966   return(!(rc = checkADname(ldap_handle, dn_path, Name)));
7967 }
7968
7969 int machine_get_moira_container(LDAP *ldap_handle, char *dn_path, 
7970                                 char *machine_name, char *container_name)
7971 {
7972   int     rc;
7973   char    *av[2];
7974   char    *call_args[2];
7975   
7976   av[0] = machine_name;
7977   call_args[0] = (char *)container_name;
7978   rc = mr_query("get_machine_to_container_map", 1, av, 
7979                 machine_GetMoiraContainer, call_args);
7980   return(rc);
7981 }
7982
7983 int machine_GetMoiraContainer(int ac, char **av, void *ptr)
7984 {
7985   char **call_args;
7986   
7987   call_args = ptr;
7988   strcpy(call_args[0], av[1]);
7989   return(0);
7990 }
7991
7992 int Moira_container_group_create(char **after)
7993 {
7994   long rc;
7995   char GroupName[64];
7996   char *argv[20];
7997   
7998   memset(GroupName, '\0', sizeof(GroupName));
7999   rc = Moira_groupname_create(GroupName, after[CONTAINER_NAME], 
8000                               after[CONTAINER_ROWID]);
8001   if (rc)
8002     return rc;
8003   
8004   argv[L_NAME] = GroupName;
8005   argv[L_ACTIVE] = "1";
8006   argv[L_PUBLIC] = "0";
8007   argv[L_HIDDEN] = "0";
8008   argv[L_MAILLIST] = "0";
8009   argv[L_GROUP] = "1";
8010   argv[L_GID] = UNIQUE_GID;
8011   argv[L_NFSGROUP] = "0";
8012   argv[L_MAILMAN] = "0";
8013   argv[L_MAILMAN_SERVER] = "[NONE]";
8014   argv[L_DESC] = "auto created container group";
8015   argv[L_ACE_TYPE] = "USER";
8016   argv[L_MEMACE_TYPE] = "USER";
8017   argv[L_ACE_NAME] = "sms";
8018   argv[L_MEMACE_NAME] = "sms";
8019
8020   if (rc = mr_query("add_list", 15, argv, NULL, NULL))
8021     {
8022       com_err(whoami, 0, 
8023               "Unable to create container group %s for container %s: %s",
8024               GroupName, after[CONTAINER_NAME], error_message(rc));
8025     }
8026
8027   Moira_setContainerGroup(after[CONTAINER_NAME], GroupName);
8028   Moira_addGroupToParent(after[CONTAINER_NAME], GroupName);
8029   
8030   return(rc);
8031 }
8032
8033 int Moira_container_group_update(char **before, char **after)
8034 {
8035   long rc;
8036   char BeforeGroupName[64];
8037   char AfterGroupName[64];
8038   char *argv[20];
8039   
8040   if (!strcasecmp(after[CONTAINER_NAME], before[CONTAINER_NAME]))
8041     return(0);
8042
8043   memset(BeforeGroupName, '\0', sizeof(BeforeGroupName));
8044   Moira_getGroupName(after[CONTAINER_NAME], BeforeGroupName, 0);
8045   if (strlen(BeforeGroupName) == 0)
8046     return(0);
8047
8048   memset(AfterGroupName, '\0', sizeof(AfterGroupName));
8049   rc = Moira_groupname_create(AfterGroupName, after[CONTAINER_NAME], 
8050                               after[CONTAINER_ROWID]);
8051   if (rc)
8052     return rc;
8053
8054   if (strcasecmp(BeforeGroupName, AfterGroupName))
8055     {
8056       argv[L_NAME] = BeforeGroupName;
8057       argv[L_NAME + 1] = AfterGroupName;
8058       argv[L_ACTIVE + 1] = "1";
8059       argv[L_PUBLIC + 1] = "0";
8060       argv[L_HIDDEN + 1] = "0";
8061       argv[L_MAILLIST + 1] = "0";
8062       argv[L_GROUP + 1] = "1";
8063       argv[L_GID + 1] = UNIQUE_GID;
8064       argv[L_NFSGROUP + 1] = "0";
8065       argv[L_MAILMAN + 1] = "0";
8066       argv[L_MAILMAN_SERVER + 1] = "[NONE]";
8067       argv[L_DESC + 1] = "auto created container group";
8068       argv[L_ACE_TYPE + 1] = "USER";
8069       argv[L_MEMACE_TYPE + 1] = "USER";
8070       argv[L_ACE_NAME + 1] = "sms";
8071       argv[L_MEMACE_NAME + 1] = "sms";
8072       
8073       if (rc = mr_query("update_list", 16, argv, NULL, NULL))
8074         {
8075           com_err(whoami, 0, 
8076                   "Unable to rename container group from %s to %s: %s",
8077                   BeforeGroupName, AfterGroupName, error_message(rc));
8078         }
8079     }
8080   
8081   return(rc);
8082 }
8083
8084 int Moira_container_group_delete(char **before)
8085 {
8086   long rc = 0;
8087   char *argv[13];
8088   char GroupName[64];
8089   char ParentGroupName[64];
8090   
8091   memset(ParentGroupName, '\0', sizeof(ParentGroupName));
8092   Moira_getGroupName(before[CONTAINER_NAME], ParentGroupName, 1);
8093
8094   memset(GroupName, '\0', sizeof(GroupName));
8095
8096   if (strcmp(before[CONTAINER_GROUP_NAME], "[none]"))
8097     strcpy(GroupName, before[CONTAINER_GROUP_NAME]);
8098   
8099   if ((strlen(ParentGroupName) != 0) && (strlen(GroupName) != 0))
8100     {
8101       argv[0] = ParentGroupName;
8102       argv[1] = "LIST";
8103       argv[2] = GroupName;
8104
8105       if (rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL))
8106         {
8107           com_err(whoami, 0, 
8108                   "Unable to delete container group %s from list: %s",
8109                   GroupName, ParentGroupName, error_message(rc));
8110         }
8111     }
8112   
8113   if (strlen(GroupName) != 0)
8114     {
8115       argv[0] = GroupName;
8116
8117       if (rc = mr_query("delete_list", 1, argv, NULL, NULL))
8118         {
8119           com_err(whoami, 0, "Unable to delete container group %s : %s",
8120                   GroupName, error_message(rc));
8121         }
8122     }
8123   
8124   return(rc);
8125 }
8126
8127 int Moira_groupname_create(char *GroupName, char *ContainerName,
8128                            char *ContainerRowID)
8129 {
8130   char *ptr;
8131   char *ptr1;
8132   char temp[64];
8133   char newGroupName[64];
8134   char tempGroupName[64];
8135   char tempgname[64];
8136   char *argv[1];
8137   int  i;
8138   long rc;
8139
8140   strcpy(temp, ContainerName);
8141   
8142   ptr1 = strrchr(temp, '/');
8143
8144   if (ptr1 != NULL)
8145   {
8146     *ptr1 = '\0';
8147     ptr = ++ptr1;
8148     ptr1 = strrchr(temp, '/');
8149
8150     if (ptr1 != NULL)
8151     {
8152         sprintf(tempgname, "%s-%s", ++ptr1, ptr);
8153     }
8154     else
8155         strcpy(tempgname, ptr);
8156   }
8157   else
8158     strcpy(tempgname, temp);
8159
8160   if (strlen(tempgname) > 25)
8161     tempgname[25] ='\0';
8162
8163   sprintf(newGroupName, "cnt-%s", tempgname);
8164
8165   /* change everything to lower case */
8166   ptr = newGroupName;
8167
8168   while (*ptr)
8169     {
8170       if (isupper(*ptr))
8171         *ptr = tolower(*ptr);
8172
8173       if (*ptr == ' ')
8174         *ptr = '-';
8175
8176       ptr++;
8177     }
8178
8179   strcpy(tempGroupName, newGroupName);
8180   i = (int)'0';
8181
8182   /* append 0-9 then a-z if a duplicate is found */
8183   while(1)
8184     {
8185       argv[0] = newGroupName;
8186
8187       if (rc = mr_query("get_list_info", 1, argv, NULL, NULL))
8188         {
8189           if (rc == MR_NO_MATCH)
8190             break;
8191           com_err(whoami, 0, "Moira error while creating group name for "
8192                   "container %s : %s", ContainerName, error_message(rc));
8193           return rc;
8194         }
8195
8196       sprintf(newGroupName, "%s-%c", tempGroupName, i);
8197
8198       if (i == (int)'z')
8199         {
8200           com_err(whoami, 0, "Unable to find a unique group name for "
8201                   "container %s: too many duplicate container names",
8202                   ContainerName);
8203           return 1;
8204         }
8205
8206       if (i == '9')
8207         i = 'a';
8208       else
8209         i++;
8210     }
8211
8212   strcpy(GroupName, newGroupName);
8213   return(0);
8214 }
8215
8216 int Moira_setContainerGroup(char *origContainerName, char *GroupName)
8217 {
8218   long rc;
8219   char *argv[3];
8220   
8221   argv[0] = origContainerName;
8222   argv[1] = GroupName;
8223   
8224   if ((rc = mr_query("set_container_list", 2, argv, NULL, NULL)))
8225     {
8226       com_err(whoami, 0, 
8227               "Unable to set container group %s in container %s: %s",
8228               GroupName, origContainerName, error_message(rc));
8229     }
8230   
8231   return(0);
8232 }
8233
8234 int Moira_addGroupToParent(char *origContainerName, char *GroupName)
8235  {
8236    char ContainerName[64];
8237    char ParentGroupName[64];
8238    char *argv[3];
8239    long rc;
8240
8241    strcpy(ContainerName, origContainerName);
8242    
8243    Moira_getGroupName(ContainerName, ParentGroupName, 1);
8244
8245    /* top-level container */
8246    if (strlen(ParentGroupName) == 0)
8247      return(0);
8248    
8249    argv[0] = ParentGroupName;
8250    argv[1] = "LIST";
8251    argv[2] = GroupName;
8252
8253    if ((rc = mr_query("add_member_to_list", 3, argv, NULL, NULL)))
8254      {
8255        com_err(whoami, 0, 
8256                "Unable to add container group %s to parent group %s: %s",
8257                GroupName, ParentGroupName, error_message(rc));
8258      }
8259    
8260    return(0);
8261  }
8262
8263 int Moira_getContainerGroup(int ac, char **av, void *ptr)
8264 {
8265   char **call_args;
8266   
8267   call_args = ptr;
8268   strcpy(call_args[0], av[1]);
8269
8270   return(0);
8271 }
8272
8273 int Moira_getGroupName(char *origContainerName, char *GroupName,
8274                        int ParentFlag)
8275 {
8276   char ContainerName[64];
8277   char *argv[3];
8278   char *call_args[3];
8279   char *ptr;
8280   long rc;
8281
8282   strcpy(ContainerName, origContainerName);
8283
8284   if (ParentFlag)
8285     {
8286       ptr = strrchr(ContainerName, '/');
8287
8288       if (ptr != NULL)
8289         (*ptr) = '\0';
8290       else
8291         return(0);
8292     }
8293
8294   argv[0] = ContainerName;
8295   argv[1] = NULL;
8296   call_args[0] = GroupName;
8297   call_args[1] = NULL;
8298
8299   if (!(rc = mr_query("get_container_list", 1, argv, Moira_getContainerGroup,
8300                       call_args)))
8301     {
8302       if (strlen(GroupName) != 0)
8303         return(0);
8304     }
8305
8306   if (rc)
8307     com_err(whoami, 0, "Unable to get container group from container %s: %s",
8308             ContainerName, error_message(rc));
8309   else
8310     com_err(whoami, 0, "Unable to get container group from container %s",
8311             ContainerName);
8312   
8313   return(0);
8314 }
8315
8316 int Moira_process_machine_container_group(char *MachineName, char* GroupName, 
8317                                           int DeleteMachine)
8318 {
8319   char *argv[3];
8320   long rc;
8321   
8322   if (strcmp(GroupName, "[none]") == 0)
8323     return 0;
8324
8325   argv[0] = GroupName;
8326   argv[1] = "MACHINE";
8327   argv[2] = MachineName;
8328
8329   if (!DeleteMachine)
8330     rc = mr_query("add_member_to_list", 3, argv, NULL, NULL);
8331   else
8332     rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL);
8333
8334   if (rc)
8335     {
8336       com_err(whoami, 0, "Unable to add machine %s to container group%s: %s",
8337               MachineName, GroupName, error_message(rc));
8338     }
8339
8340   return(0);
8341 }
8342
8343 int GetMachineName(char *MachineName)
8344 {
8345   char    *args[2];
8346   char    NewMachineName[1024];
8347   char    *szDot;
8348   int     rc = 0;
8349   int     i;
8350   DWORD   dwLen = 0;
8351   char    *call_args[2];
8352   
8353   // If the address happens to be in the top-level MIT domain, great!
8354   strcpy(NewMachineName, MachineName);
8355
8356   for (i = 0; i < (int)strlen(NewMachineName); i++)
8357     NewMachineName[i] = toupper(NewMachineName[i]);
8358
8359   szDot = strchr(NewMachineName,'.');
8360
8361   if ((szDot) && (!strcasecmp(szDot+1, DOMAIN_SUFFIX)))
8362     {
8363       return(0);
8364     }
8365   
8366   // If not, see if it has a Moira alias in the top-level MIT domain.
8367   memset(NewMachineName, '\0', sizeof(NewMachineName));
8368   args[0] = "*";
8369   args[1] = MachineName;
8370   call_args[0] = NewMachineName;
8371   call_args[1] = NULL;
8372
8373   if (rc = mr_query("get_hostalias", 2, args, ProcessMachineName, call_args))
8374     {
8375       com_err(whoami, 0, "Unable to resolve machine name %s : %s",
8376               MachineName, error_message(rc));
8377       strcpy(MachineName, "");
8378       return(0);
8379     }
8380   
8381   if (strlen(NewMachineName) != 0)
8382     strcpy(MachineName, NewMachineName);
8383   else
8384     strcpy(MachineName, "");
8385
8386   return(0);
8387 }
8388
8389 int ProcessMachineName(int ac, char **av, void *ptr)
8390 {
8391   char    **call_args;
8392   char    MachineName[1024];
8393   char    *szDot;
8394   int     i;
8395   
8396   call_args = ptr;
8397
8398   if (strlen(call_args[0]) == 0)
8399     {
8400       strcpy(MachineName, av[0]);
8401
8402       for (i = 0; i < (int)strlen(MachineName); i++)
8403         MachineName[i] = toupper(MachineName[i]);
8404
8405       szDot = strchr(MachineName,'.');
8406
8407         if ((szDot) && (!strcasecmp(szDot+1,DOMAIN_SUFFIX)))
8408           {
8409             strcpy(call_args[0], MachineName);
8410           }
8411     }
8412
8413   return(0);
8414 }
8415
8416 void SwitchSFU(LDAPMod **mods, int *UseSFU30, int n)
8417 {
8418   int i;
8419   
8420   if (*UseSFU30)
8421     {
8422       for (i = 0; i < n; i++)
8423         {
8424           if (!strcmp(mods[i]->mod_type, "msSFU30UidNumber"))
8425             mods[i]->mod_type = "uidNumber";
8426         }
8427
8428       (*UseSFU30) = 0;
8429     }
8430   else
8431     {
8432       for (i = 0; i < n; i++)
8433         {
8434           if (!strcmp(mods[i]->mod_type, "uidNumber"))
8435             mods[i]->mod_type = "msSFU30UidNumber";
8436         }
8437
8438       (*UseSFU30) = 1;
8439     }
8440 }
8441
8442 int SetHomeDirectory(LDAP *ldap_handle, char *user_name, 
8443                      char *DistinguishedName,
8444                      char *WinHomeDir, char *WinProfileDir,
8445                      char **homedir_v, char **winProfile_v,
8446                      char **drives_v, LDAPMod **mods, 
8447                      int OpType, int n)
8448 {
8449   char cWeight[3];
8450   char cPath[1024];
8451   char path[1024];
8452   char winPath[1024];
8453   char winProfile[1024];
8454   char homeDrive[8];
8455   char homedir[1024];
8456   char apple_homedir[1024];
8457   char *apple_homedir_v[] = {NULL, NULL};
8458   int  last_weight;
8459   int  i;
8460   int  rc;
8461   LDAPMod *DelMods[20];
8462   char *argv[3];
8463   char *save_argv[FS_END];
8464   char *fsgroup_save_argv[2];
8465
8466   memset(homeDrive, '\0', sizeof(homeDrive));
8467   memset(path, '\0', sizeof(path));
8468   memset(winPath, '\0', sizeof(winPath));
8469   memset(winProfile, '\0', sizeof(winProfile));
8470
8471   if(!ActiveDirectory) 
8472     {
8473       if (rc = moira_connect())
8474         {
8475           critical_alert(whoami, "Ldap incremental",
8476                          "Error contacting Moira server : %s",
8477                          error_message(rc));
8478           return;
8479         }
8480       
8481       argv[0] = user_name;
8482
8483       if (!(rc = mr_query("get_filesys_by_label", 1, argv, save_query_info, 
8484                           save_argv)))
8485         {
8486           if(!strcmp(save_argv[FS_TYPE], "FSGROUP") ||
8487              !strcmp(save_argv[FS_TYPE], "MUL"))
8488             {
8489         
8490               argv[0] = save_argv[FS_NAME];
8491               fsgCount = 0;
8492               
8493               if (!(rc = mr_query("get_fsgroup_members", 1, argv, 
8494                                   save_fsgroup_info, fsgroup_save_argv)))
8495                 {
8496                   if(fsgCount)
8497                     {
8498                       argv[0] = fsgroup_save_argv[0];
8499                       
8500                       if (!(rc = mr_query("get_filesys_by_label", 1, argv, 
8501                                           save_query_info, save_argv)))
8502                         {
8503                           strcpy(path, save_argv[FS_PACK]);
8504                         }
8505                     }
8506                 }
8507             }
8508           else
8509             {
8510               strcpy(path, save_argv[FS_PACK]);
8511             }
8512         }
8513       
8514       moira_disconnect();
8515
8516       if (strlen(path))
8517         {
8518           if (!strnicmp(path, AFS, strlen(AFS)))
8519             {
8520               sprintf(homedir, "%s", path);
8521               sprintf(apple_homedir, "%s/MacData", path);
8522               homedir_v[0] = homedir;
8523               apple_homedir_v[0] = apple_homedir;
8524               ADD_ATTR("homeDirectory", homedir_v, OpType);
8525               ADD_ATTR("apple-user-homeDirectory", apple_homedir_v, 
8526                        OpType);
8527             }
8528         }
8529       else
8530         {
8531           homedir_v[0] = "NONE";
8532           apple_homedir_v[0] = "NONE";
8533           ADD_ATTR("homeDirectory", homedir_v, OpType);
8534           ADD_ATTR("apple-user-homeDirectory", apple_homedir_v, 
8535                    OpType);
8536         }
8537
8538       return(n);
8539     }
8540  
8541   if ((!strcasecmp(WinHomeDir, "[afs]")) || 
8542       (!strcasecmp(WinProfileDir, "[afs]")))
8543     {
8544       if (rc = moira_connect())
8545         {
8546           critical_alert(whoami, "Ldap incremental",
8547                          "Error contacting Moira server : %s",
8548                          error_message(rc));
8549           return;
8550         }
8551       
8552       argv[0] = user_name;
8553
8554       if (!(rc = mr_query("get_filesys_by_label", 1, argv, save_query_info, 
8555                           save_argv)))
8556         {
8557           if(!strcmp(save_argv[FS_TYPE], "FSGROUP") ||
8558              !strcmp(save_argv[FS_TYPE], "MUL"))
8559             {
8560         
8561               argv[0] = save_argv[FS_NAME];
8562               fsgCount = 0;
8563               
8564               if (!(rc = mr_query("get_fsgroup_members", 1, argv, 
8565                                   save_fsgroup_info, fsgroup_save_argv)))
8566                 {
8567                   if(fsgCount)
8568                     {
8569                       argv[0] = fsgroup_save_argv[0];
8570                       
8571                       if (!(rc = mr_query("get_filesys_by_label", 1, argv, 
8572                                           save_query_info, save_argv)))
8573                         {
8574                           strcpy(path, save_argv[FS_PACK]);
8575                         }
8576                     }
8577                 }
8578             }
8579           else
8580             {
8581               strcpy(path, save_argv[FS_PACK]);
8582             }
8583         }
8584      
8585       moira_disconnect();
8586
8587       if (strlen(path))
8588         {
8589           if (!strnicmp(path, AFS, strlen(AFS)))
8590             {
8591               AfsToWinAfs(path, winPath);
8592               strcpy(winProfile, winPath);
8593               strcat(winProfile, "\\.winprofile");
8594             }
8595         }
8596       else
8597         return(n);
8598     }
8599
8600     if ((!strcasecmp(WinHomeDir, "[dfs]")) || 
8601         (!strcasecmp(WinProfileDir, "[dfs]")))
8602     {
8603       sprintf(path, "\\\\%s\\dfs\\profiles\\%c\\%s", ldap_domain, 
8604               user_name[0], user_name);
8605
8606       if (!strcasecmp(WinProfileDir, "[dfs]"))
8607         {
8608           strcpy(winProfile, path);
8609           strcat(winProfile, "\\.winprofile");
8610         }
8611
8612       if (!strcasecmp(WinHomeDir, "[dfs]"))
8613         strcpy(winPath, path);
8614     }
8615     
8616     if (!strcasecmp(WinHomeDir, "[local]"))
8617       memset(winPath, '\0', sizeof(winPath));
8618     else if (!strcasecmp(WinHomeDir, "[afs]") || 
8619              !strcasecmp(WinHomeDir, "[dfs]"))
8620       {
8621         strcpy(homeDrive, "H:");
8622       }
8623     else
8624       {
8625         strcpy(winPath, WinHomeDir);
8626         if (!strncmp(WinHomeDir, "\\\\", 2))
8627           {
8628             strcpy(homeDrive, "H:");
8629           }        
8630       }
8631     
8632     // nothing needs to be done if WinProfileDir is [afs].
8633     if (!strcasecmp(WinProfileDir, "[local]"))
8634       memset(winProfile, '\0', sizeof(winProfile));
8635     else if (strcasecmp(WinProfileDir, "[afs]") && 
8636              strcasecmp(WinProfileDir, "[dfs]"))
8637       {
8638         strcpy(winProfile, WinProfileDir);
8639       }
8640     
8641     if (strlen(winProfile) != 0)
8642       {
8643         if (winProfile[strlen(winProfile) - 1] == '\\')
8644           winProfile[strlen(winProfile) - 1] = '\0';
8645       }
8646
8647     if (strlen(winPath) != 0)
8648       {
8649         if (winPath[strlen(winPath) - 1] == '\\')
8650           winPath[strlen(winPath) - 1] = '\0';
8651       }
8652     
8653     if ((winProfile[1] == ':') && (strlen(winProfile) == 2))
8654       strcat(winProfile, "\\");
8655
8656     if ((winPath[1] == ':') && (strlen(winPath) == 2))
8657       strcat(winPath, "\\");
8658     
8659     if (strlen(winPath) == 0)
8660       {
8661         if (OpType == LDAP_MOD_REPLACE)
8662           {
8663             i = 0;
8664             DEL_ATTR("homeDirectory", LDAP_MOD_DELETE);
8665             DelMods[i] = NULL;
8666             //unset homeDirectory attribute for user.
8667             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
8668             free(DelMods[0]);
8669           }
8670       }
8671     else
8672       {
8673         homedir_v[0] = strdup(winPath);
8674         ADD_ATTR("homeDirectory", homedir_v, OpType);
8675       }
8676     
8677     if (strlen(winProfile) == 0)
8678       {
8679         if (OpType == LDAP_MOD_REPLACE)
8680           {
8681             i = 0;
8682             DEL_ATTR("profilePath", LDAP_MOD_DELETE);
8683             DelMods[i] = NULL;
8684             //unset profilePate attribute for user.
8685             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
8686             free(DelMods[0]);
8687           }
8688       }
8689     else
8690       {
8691         winProfile_v[0] = strdup(winProfile);
8692         ADD_ATTR("profilePath", winProfile_v, OpType);
8693       }
8694     
8695     if (strlen(homeDrive) == 0)
8696       {
8697         if (OpType == LDAP_MOD_REPLACE)
8698           {
8699             i = 0;
8700             DEL_ATTR("homeDrive", LDAP_MOD_DELETE);
8701             DelMods[i] = NULL;
8702             //unset homeDrive attribute for user
8703             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
8704             free(DelMods[0]);
8705           }
8706       }
8707     else
8708       {
8709         drives_v[0] = strdup(homeDrive);
8710         ADD_ATTR("homeDrive", drives_v, OpType);
8711       }
8712
8713     return(n);
8714 }
8715
8716 int attribute_update(LDAP *ldap_handle, char *distinguished_name, 
8717                      char *attribute_value, char *attribute, char *user_name)
8718 {
8719   char      *mod_v[] = {NULL, NULL};
8720   LDAPMod   *DelMods[20];
8721   LDAPMod   *mods[20];
8722   int       n;
8723   int       i;
8724   int       rc;
8725   
8726   if (strlen(attribute_value) == 0)
8727     {
8728       i = 0;
8729       DEL_ATTR(attribute, LDAP_MOD_DELETE);
8730       DelMods[i] = NULL;
8731       rc = ldap_modify_s(ldap_handle, distinguished_name, DelMods);
8732       free(DelMods[0]);
8733     }
8734   else
8735     {
8736       n = 0;
8737       mod_v[0] = attribute_value;
8738       ADD_ATTR(attribute, mod_v, LDAP_MOD_REPLACE);
8739       mods[n] = NULL;
8740
8741       if ((rc = ldap_modify_s(ldap_handle, distinguished_name, 
8742                               mods)) != LDAP_SUCCESS)
8743         {
8744           free(mods[0]);
8745           n = 0;
8746           mod_v[0] = attribute_value;
8747           ADD_ATTR(attribute, mod_v, LDAP_MOD_ADD);
8748           mods[n] = NULL;
8749
8750           if ((rc = ldap_modify_s(ldap_handle, distinguished_name, 
8751                                   mods)) != LDAP_SUCCESS)
8752             {
8753               com_err(whoami, 0, "Unable to change the %s attribute for %s "
8754                       "in the directory : %s",
8755                       attribute, user_name, ldap_err2string(rc));
8756             }
8757         }
8758
8759       free(mods[0]);
8760     }
8761   
8762   return(rc);
8763 }
8764
8765 void StringTrim(char *StringToTrim)
8766 {
8767   char *t, *s;
8768   char *save;
8769
8770   save = strdup(StringToTrim);
8771
8772   s = save;
8773
8774   while (isspace(*s))
8775     s++;
8776
8777   /* skip to end of string */
8778   if (*s == '\0')
8779     {
8780       if (*save)
8781         *save = '\0';
8782       strcpy(StringToTrim, save);
8783       return;
8784     }
8785   
8786   for (t = s; *t; t++)
8787     continue;
8788
8789   while (t > s)
8790     {
8791       --t;
8792       if (!isspace(*t))
8793         {
8794           t++;
8795           break;
8796         }
8797     }
8798
8799   if (*t)
8800     *t = '\0';
8801   
8802   strcpy(StringToTrim, s);
8803   return;
8804 }
8805
8806 int ReadConfigFile(char *DomainName)
8807 {
8808     int     Count;
8809     int     i;
8810     int     k;
8811     char    temp[256];
8812     char    temp1[256];
8813     FILE    *fptr;
8814
8815     Count = 0;
8816
8817     sprintf(temp, "%s%s.cfg", CFG_PATH, DomainName);
8818
8819     if ((fptr = fopen(temp, "r")) != NULL)
8820       {
8821         while (fgets(temp, sizeof(temp), fptr) != 0)
8822           {
8823             for (i = 0; i < (int)strlen(temp); i++)
8824               temp[i] = toupper(temp[i]);
8825
8826             if (temp[strlen(temp) - 1] == '\n')
8827               temp[strlen(temp) - 1] = '\0';
8828
8829             StringTrim(temp);
8830
8831             if (strlen(temp) == 0)
8832               continue;
8833
8834             if (!strncmp(temp, DOMAIN, strlen(DOMAIN)))
8835               {
8836                 if (strlen(temp) > (strlen(DOMAIN)))
8837                   {
8838                     strcpy(ldap_domain, &temp[strlen(DOMAIN)]);
8839                     StringTrim(ldap_domain);
8840                   }
8841               }
8842             else if (!strncmp(temp, REALM, strlen(REALM)))
8843               {
8844                 if (strlen(temp) > (strlen(REALM)))
8845                   {
8846                     strcpy(ldap_realm, &temp[strlen(REALM)]);
8847                     StringTrim(ldap_realm);
8848                   }
8849               }
8850             else if (!strncmp(temp, PORT, strlen(PORT)))
8851               {
8852                 if (strlen(temp) > (strlen(PORT)))
8853                   {
8854                     strcpy(ldap_port, &temp[strlen(PORT)]);
8855                     StringTrim(ldap_port);
8856                   }
8857               }
8858             else if (!strncmp(temp, PRINCIPALNAME, strlen(PRINCIPALNAME)))
8859               {
8860                 if (strlen(temp) > (strlen(PRINCIPALNAME)))
8861                   {
8862                     strcpy(PrincipalName, &temp[strlen(PRINCIPALNAME)]);
8863                     StringTrim(PrincipalName);
8864                   }
8865               }
8866             else if (!strncmp(temp, SERVER, strlen(SERVER)))
8867               {
8868                 if (strlen(temp) > (strlen(SERVER)))
8869                   {
8870                     ServerList[Count] = calloc(1, 256);
8871                     strcpy(ServerList[Count], &temp[strlen(SERVER)]);
8872                     StringTrim(ServerList[Count]);
8873                     ++Count;
8874                   }
8875               }
8876             else if (!strncmp(temp, MSSFU, strlen(MSSFU)))
8877               {
8878                 if (strlen(temp) > (strlen(MSSFU)))
8879                   {
8880                     strcpy(temp1, &temp[strlen(MSSFU)]);
8881                     StringTrim(temp1);
8882                     if (!strcmp(temp1, SFUTYPE))
8883                       UseSFU30 = 1;
8884                   }
8885               }
8886             else if (!strncmp(temp, GROUP_SUFFIX, strlen(GROUP_SUFFIX)))
8887               {
8888                 if (strlen(temp) > (strlen(GROUP_SUFFIX)))
8889                   {
8890                     strcpy(temp1, &temp[strlen(GROUP_SUFFIX)]);
8891                     StringTrim(temp1);
8892                     if (!strcasecmp(temp1, "NO")) 
8893                       {
8894                         UseGroupSuffix = 0;
8895                         memset(group_suffix, '\0', sizeof(group_suffix));
8896                       }
8897                   }
8898               }
8899             else if (!strncmp(temp, GROUP_TYPE, strlen(GROUP_TYPE)))
8900               {
8901                 if (strlen(temp) > (strlen(GROUP_TYPE)))
8902                   {
8903                     strcpy(temp1, &temp[strlen(GROUP_TYPE)]);
8904                     StringTrim(temp1);
8905                     if (!strcasecmp(temp1, "UNIVERSAL")) 
8906                       UseGroupUniversal = 1;
8907                   }
8908               }
8909             else if (!strncmp(temp, SET_GROUP_ACE, strlen(SET_GROUP_ACE)))
8910               {
8911                 if (strlen(temp) > (strlen(SET_GROUP_ACE)))
8912                   {
8913                     strcpy(temp1, &temp[strlen(SET_GROUP_ACE)]);
8914                     StringTrim(temp1);
8915                     if (!strcasecmp(temp1, "NO"))
8916                       SetGroupAce = 0;
8917                   }
8918               }
8919             else if (!strncmp(temp, SET_PASSWORD, strlen(SET_PASSWORD)))
8920               {
8921                 if (strlen(temp) > (strlen(SET_PASSWORD)))
8922                   {
8923                     strcpy(temp1, &temp[strlen(SET_PASSWORD)]);
8924                     StringTrim(temp1);
8925                     if (!strcasecmp(temp1, "NO"))
8926                       SetPassword = 0;
8927                   }
8928               }
8929             else if (!strncmp(temp, EXCHANGE, strlen(EXCHANGE)))
8930               {
8931                 if (strlen(temp) > (strlen(EXCHANGE)))
8932                   {
8933                     strcpy(temp1, &temp[strlen(EXCHANGE)]);
8934                     StringTrim(temp1);
8935                     if (!strcasecmp(temp1, "YES"))
8936                       Exchange = 1;
8937                   }
8938               }
8939             else if (!strncmp(temp, PROCESS_MACHINE_CONTAINER, 
8940                               strlen(PROCESS_MACHINE_CONTAINER)))
8941               {
8942                 if (strlen(temp) > (strlen(PROCESS_MACHINE_CONTAINER)))
8943                   {
8944                     strcpy(temp1, &temp[strlen(PROCESS_MACHINE_CONTAINER)]);
8945                     StringTrim(temp1);
8946                     if (!strcasecmp(temp1, "NO"))
8947                       ProcessMachineContainer = 0;
8948                   }
8949               }
8950             else if (!strncmp(temp, ACTIVE_DIRECTORY, 
8951                               strlen(ACTIVE_DIRECTORY)))
8952               {
8953                 if (strlen(temp) > (strlen(ACTIVE_DIRECTORY)))
8954                   {
8955                     strcpy(temp1, &temp[strlen(ACTIVE_DIRECTORY)]);
8956                     StringTrim(temp1);
8957                     if (!strcasecmp(temp1, "NO"))
8958                       ActiveDirectory = 0;
8959                   }
8960               }
8961             else if (!strncmp(temp, GROUP_POPULATE_MEMBERS, 
8962                               strlen(GROUP_POPULATE_MEMBERS)))
8963               {
8964                 if (strlen(temp) > (strlen(GROUP_POPULATE_MEMBERS)))
8965                   {
8966                     strcpy(temp1, &temp[strlen(GROUP_POPULATE_MEMBERS)]);
8967                     StringTrim(temp1);
8968                     if (!strcasecmp(temp1, "DELETE")) 
8969                       {
8970                         GroupPopulateDelete = 1;
8971                       }
8972                   }
8973               }
8974             else if (!strncmp(temp, MAX_MEMBERS, strlen(MAX_MEMBERS)))
8975               {
8976                 if (strlen(temp) > (strlen(MAX_MEMBERS)))
8977                   {
8978                     strcpy(temp1, &temp[strlen(MAX_MEMBERS)]);
8979                     StringTrim(temp1);
8980                     max_group_members = atoi(temp1);
8981                   }
8982               }
8983             else
8984               {
8985                 if (strlen(ldap_domain) != 0)
8986                   {
8987                     memset(ldap_domain, '\0', sizeof(ldap_domain));
8988                     break;
8989                   }
8990
8991                 if (strlen(temp) != 0)
8992                   strcpy(ldap_domain, temp);
8993               }
8994           }
8995         fclose(fptr);
8996       }
8997     
8998     if (strlen(ldap_domain) == 0)
8999       {
9000       strcpy(ldap_domain, DomainName);
9001       }
9002
9003     if (Count == 0)
9004         return(0);
9005
9006     for (i = 0; i < Count; i++)
9007       {
9008         if (ServerList[i] != 0)
9009           {
9010             for (k = 0; k < (int)strlen(ServerList[i]); k++)
9011               ServerList[i][k] = toupper(ServerList[i][k]);
9012           }
9013       }
9014     
9015     return(0);
9016 }
9017
9018 int ReadDomainList()
9019 {
9020   int     Count;
9021   int     i;
9022   char    temp[128];
9023   char    temp1[128];
9024   FILE    *fptr;
9025   unsigned char c[11];
9026   unsigned char stuff[256];
9027   int     rc;
9028   int     ok;
9029
9030   Count = 0;
9031   sprintf(temp, "%s%s", CFG_PATH, WINADCFG);
9032
9033   if ((fptr = fopen(temp, "r")) != NULL)
9034     {
9035       while (fgets(temp, sizeof(temp), fptr) != 0)
9036         {
9037           for (i = 0; i < (int)strlen(temp); i++)
9038             temp[i] = toupper(temp[i]);
9039
9040           if (temp[strlen(temp) - 1] == '\n')
9041             temp[strlen(temp) - 1] = '\0';
9042
9043           StringTrim(temp);
9044
9045           if (strlen(temp) == 0)
9046             continue;
9047
9048           if (!strncmp(temp, DOMAIN, strlen(DOMAIN)))
9049             {
9050               if (strlen(temp) > (strlen(DOMAIN)))
9051                 {
9052                   strcpy(temp1, &temp[strlen(DOMAIN)]);
9053                   StringTrim(temp1);
9054                   strcpy(temp, temp1);
9055                 }
9056             }
9057           
9058           strcpy(DomainNames[Count], temp);
9059           StringTrim(DomainNames[Count]);
9060           ++Count;
9061         }
9062
9063       fclose(fptr);
9064     }
9065
9066   if (Count == 0)
9067     {
9068       critical_alert(whoami, "incremental", "%s", "ldap.incr cannot run due to a "
9069                      "configuration error in ldap.cfg");
9070       return(1);
9071     }
9072   
9073   return(0);
9074 }
9075
9076 int email_isvalid(const char *address) {
9077   int        count = 0;
9078   const char *c, *domain;
9079   static char *rfc822_specials = "()<>@,;:\\\"[]";
9080
9081   if(address[strlen(address) - 1] == '.') 
9082     return 0;
9083     
9084   /* first we validate the name portion (name@domain) */
9085   for (c = address;  *c;  c++) {
9086     if (*c == '\"' && (c == address || *(c - 1) == '.' || *(c - 1) == 
9087                        '\"')) {
9088       while (*++c) {
9089         if (*c == '\"') 
9090           break;
9091         if (*c == '\\' && (*++c == ' ')) 
9092           continue;
9093         if (*c <= ' ' || *c >= 127) 
9094           return 0;
9095       }
9096
9097       if (!*c++) 
9098         return 0;
9099       if (*c == '@') 
9100         break;
9101       if (*c != '.') 
9102         return 0;
9103       continue;
9104     }
9105
9106     if (*c == '@') 
9107       break;
9108     if (*c <= ' ' || *c >= 127) 
9109       return 0;
9110     if (strchr(rfc822_specials, *c)) 
9111       return 0;
9112   }
9113
9114   if (c == address || *(c - 1) == '.') 
9115     return 0;
9116
9117   /* next we validate the domain portion (name@domain) */
9118   if (!*(domain = ++c)) return 0;
9119   do {
9120     if (*c == '.') {
9121       if (c == domain || *(c - 1) == '.') 
9122         return 0;
9123       count++;
9124     }
9125     if (*c <= ' ' || *c >= 127) 
9126       return 0;
9127     if (strchr(rfc822_specials, *c)) 
9128       return 0;
9129   } while (*++c);
9130
9131   return (count >= 1);
9132 }
9133
9134 int find_homeMDB(LDAP *ldap_handle, char *dn_path, char **homeMDB, 
9135              char **homeServerName) 
9136 {
9137   LK_ENTRY *group_base;
9138   LK_ENTRY *sub_group_base;
9139   LK_ENTRY *gPtr;
9140   LK_ENTRY *sub_gPtr;
9141   int      group_count;
9142   int      sub_group_count;
9143   char     filter[1024];
9144   char     sub_filter[1024];
9145   char     search_path[1024];
9146   char     range[1024];
9147   char     *attr_array[3];
9148   char     *s;
9149   int      homeMDB_count = -1;
9150   int      rc;
9151   int      i;
9152   int      mdbbl_count;
9153   int      rangeStep = 1500;
9154   int      rangeLow = 0;
9155   int      rangeHigh = rangeLow + (rangeStep - 1);
9156   int      isLast = 0;
9157
9158   /* Grumble..... microsoft not making it searchable from the root *grr* */
9159
9160   memset(filter, '\0', sizeof(filter));
9161   memset(search_path, '\0', sizeof(search_path));
9162   
9163   sprintf(filter, "(objectClass=msExchMDB)");
9164   sprintf(search_path, "CN=Configuration,%s", dn_path);
9165   attr_array[0] = "distinguishedName";
9166   attr_array[1] = NULL;
9167   
9168   group_base = NULL;
9169   group_count = 0;
9170   
9171   if ((rc = linklist_build(ldap_handle, search_path, filter, attr_array,
9172                            &group_base, &group_count, 
9173                            LDAP_SCOPE_SUBTREE)) != 0) 
9174     {
9175       com_err(whoami, 0, "Unable to find msExchMDB %s",
9176               ldap_err2string(rc));
9177       return(rc);
9178     }
9179   
9180   if (group_count) 
9181     {
9182       gPtr = group_base;
9183       
9184       while(gPtr) {
9185         if (((s = strstr(gPtr->dn, "Public")) != (char *) NULL) ||
9186             ((s = strstr(gPtr->dn, "Recover")) != (char *) NULL) || 
9187             ((s = strstr(gPtr->dn, "Reserve")) != (char *) NULL))
9188           {
9189             gPtr = gPtr->next;
9190             continue;
9191           }
9192
9193         /* 
9194          * Due to limits in active directory we need to use the LDAP
9195          * range semantics to query and return all the values in 
9196          * large lists, we will stop increasing the range when
9197          * the result count is 0.
9198          */
9199
9200         i = 0;  
9201         mdbbl_count = 0;
9202
9203         for(;;) 
9204           {
9205             memset(sub_filter, '\0', sizeof(sub_filter));
9206             memset(range, '\0', sizeof(range));
9207             sprintf(sub_filter, "(objectClass=msExchMDB)");
9208
9209             if(isLast)
9210               sprintf(range, "homeMDBBL;Range=%d-*", rangeLow);
9211             else 
9212               sprintf(range, "homeMDBBL;Range=%d-%d", rangeLow, rangeHigh);
9213
9214             attr_array[0] = range;
9215             attr_array[1] = NULL;
9216             
9217             sub_group_base = NULL;
9218             sub_group_count = 0;
9219             
9220             if ((rc = linklist_build(ldap_handle, gPtr->dn, sub_filter, 
9221                                      attr_array, &sub_group_base, 
9222                                      &sub_group_count, 
9223                                      LDAP_SCOPE_SUBTREE)) != 0) 
9224               {
9225                 com_err(whoami, 0, "Unable to find homeMDBBL %s",
9226                         ldap_err2string(rc));
9227                 return(rc);
9228               }
9229
9230             if(!sub_group_count)
9231               {
9232                 if(isLast) 
9233                   {
9234                     isLast = 0;
9235                     rangeLow = 0;
9236                     rangeHigh = rangeLow + (rangeStep - 1);
9237                     break;
9238                   }
9239                 else
9240                   isLast++;
9241               }
9242
9243             mdbbl_count += sub_group_count;
9244             rangeLow = rangeHigh + 1;
9245             rangeHigh = rangeLow + (rangeStep - 1);
9246           }
9247
9248         /* First time through, need to initialize or update the least used */
9249         
9250         com_err(whoami, 0, "Mail store %s, count %d", gPtr->dn, 
9251                 mdbbl_count);
9252
9253         if(mdbbl_count < homeMDB_count || homeMDB_count == -1) 
9254           {
9255             homeMDB_count = mdbbl_count; 
9256             *homeMDB = strdup(gPtr->dn);
9257           }
9258
9259         gPtr = gPtr->next;
9260         linklist_free(sub_group_base);
9261       }
9262     }
9263
9264   linklist_free(group_base);
9265   
9266   /* 
9267    * Ok found the server least allocated need to now query to get its
9268    * msExchHomeServerName so we can set it as a user attribute
9269    */
9270   
9271   attr_array[0] = "legacyExchangeDN";
9272   attr_array[1] = NULL; 
9273   
9274   group_count = 0;
9275   group_base = NULL;
9276   
9277   if ((rc = linklist_build(ldap_handle, *homeMDB, filter, 
9278                            attr_array, &group_base, 
9279                            &group_count, 
9280                            LDAP_SCOPE_SUBTREE)) != 0) 
9281     {
9282       com_err(whoami, 0, "Unable to find msExchHomeServerName %s",
9283               ldap_err2string(rc));
9284       return(rc);
9285     }  
9286   
9287   if(group_count) 
9288     {
9289       *homeServerName = strdup(group_base->value);
9290       if((s = strrchr(*homeServerName, '/')) != (char *) NULL) 
9291         {
9292           *s = '\0';
9293         }
9294     } 
9295
9296   linklist_free(group_base);
9297   
9298   return(rc);
9299 }
9300       
9301 char *lowercase(char *s)
9302 {
9303   char *p;
9304
9305   for (p = s; *p; p++)
9306     {
9307       if (isupper(*p))
9308         *p = tolower(*p);
9309     }
9310   return s;
9311 }
9312
9313 char *uppercase(char *s)
9314 {
9315   char *p;
9316
9317   for (p = s; *p; p++)
9318     {
9319       if (islower(*p))
9320         *p = toupper(*p);
9321     }
9322   return s;
9323 }
9324
9325 char *escape_string(char *s)
9326 {
9327   char *p, *q;
9328   char string[1024];
9329   char temp[1024];
9330   int i = 0;
9331   int spaces = 0;
9332
9333   if(ActiveDirectory) {
9334     return strdup(s);
9335   }
9336
9337   memset(string, '\0', sizeof(string));
9338
9339   q = s;
9340
9341   /* Escape any special characters */
9342
9343   for(; *q != '\0'; q++) {
9344     if(*q == ',')
9345       string[i++] = '\\';
9346     if(*q == '+') 
9347       string[i++] = '\\';
9348     if(*q == '"') 
9349       string[i++] = '\\';
9350     if(*q == '\\') 
9351       string[i++] = '\\';
9352     if(*q == '<') 
9353       string[i++] = '\\';
9354     if(*q == '>') 
9355       string[i++] = '\\';
9356     if(*q == ';')
9357       string[i++] = '\\';
9358     if(*q == '#')
9359       string[i++] = '\\';
9360     if(*q == '=')
9361       string[i++] = '\\';
9362
9363     string[i++] = *q;
9364   }
9365
9366   return strdup(string);
9367 }
9368
9369 int save_query_info(int argc, char **argv, void *hint)
9370 {
9371   int i;
9372   char **nargv = hint;
9373
9374   for(i = 0; i < argc; i++)
9375     nargv[i] = strdup(argv[i]);
9376
9377   return MR_CONT;
9378 }
9379
9380 int save_fsgroup_info(int argc, char **argv, void *hint)
9381 {
9382   int i;
9383   char **nargv = hint;
9384
9385   if(!fsgCount) 
9386     {
9387       for(i = 0; i < argc; i++)
9388         nargv[i] = strdup(argv[i]);
9389
9390       fsgCount++;
9391     }
9392
9393   return MR_CONT;
9394 }
9395
9396 int contains_member(LDAP *ldap_handle, char *dn_path, char *group_name, 
9397                     char *UserOu, char *user_name)
9398 {
9399   char         search_filter[1024];
9400   char         *attr_array[3];
9401   LK_ENTRY     *group_base;
9402   int          group_count;
9403   int          rc;
9404   char         temp[256];
9405
9406   if(ActiveDirectory)
9407     {
9408       sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
9409     }
9410   else
9411     {
9412       if(!strcmp(UserOu, user_ou))
9413         sprintf(temp, "uid=%s,%s,%s", user_name, UserOu, dn_path);
9414       else
9415         sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
9416     }
9417
9418   group_base = NULL;
9419   group_count = 0;
9420   
9421   sprintf(search_filter, "(&(objectClass=group)(cn=%s)(member=%s))",
9422           group_name, temp);
9423
9424   attr_array[0] = "mitMoiraId";
9425   attr_array[1] = NULL;
9426
9427   if ((rc = linklist_build(ldap_handle, dn_path, search_filter, 
9428                            attr_array, &group_base, &group_count,
9429                            LDAP_SCOPE_SUBTREE)) != 0)
9430     {
9431       com_err(whoami, 0, "Unable to check group %s for membership of %s : %s",
9432               group_name, user_name, ldap_err2string(rc));
9433       return(-1);
9434     }
9435           
9436   if (group_count)
9437     {
9438       rc = 1;
9439     }
9440   else 
9441     {
9442       rc = 0;
9443     }
9444
9445   linklist_free(group_base);
9446   group_count = 0;
9447   group_base = NULL;
9448
9449   return(rc);
9450 }
This page took 4.636827 seconds and 5 git commands to generate.