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