]> andersk Git - moira.git/blob - incremental/ldap/winad.c
*** empty log message ***
[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   char      *null_v[] = {NULL, NULL};
2413   u_int     groupTypeControl;
2414   char      groupTypeControlStr[80];
2415   char      contact_mail[256];
2416   int       n;
2417   int       i;
2418   int       rc;
2419   LK_ENTRY  *group_base;
2420   int       group_count;
2421   int       MailDisabled = 0;
2422   char      search_filter[1024];
2423
2424   if(UseGroupUniversal)
2425     groupTypeControl = ADS_GROUP_TYPE_UNIVERSAL_GROUP;
2426   else
2427     groupTypeControl = ADS_GROUP_TYPE_GLOBAL_GROUP;
2428      
2429   if (!check_string(before_group_name))
2430     {
2431       com_err(whoami, 0, 
2432               "Unable to process invalid LDAP list name %s", 
2433               before_group_name);
2434       return(AD_INVALID_NAME);
2435     }
2436
2437   if (!check_string(after_group_name))
2438     {
2439       com_err(whoami, 0, 
2440               "Unable to process invalid LDAP list name %s", after_group_name);
2441       return(AD_INVALID_NAME);
2442     }
2443
2444   if (Exchange) 
2445     {
2446       if(atoi(maillist)) 
2447         {
2448           group_count = 0;
2449           group_base = NULL;
2450           
2451           sprintf(search_filter, "(&(objectClass=user)(cn=%s))", 
2452                   after_group_name);
2453           attr_array[0] = "cn";
2454           attr_array[1] = NULL;
2455
2456           if ((rc = linklist_build(ldap_handle, dn_path, search_filter, 
2457                                    attr_array, &group_base, &group_count,
2458                                    LDAP_SCOPE_SUBTREE)) != 0)
2459           {
2460             com_err(whoami, 0, "Unable to process group %s : %s",
2461                     after_group_name, ldap_err2string(rc));
2462             return(rc);
2463           }
2464           
2465           if (group_count)
2466             {
2467               com_err(whoami, 0, "Object already exists with name %s",
2468                       after_group_name);
2469               MailDisabled++;
2470             }
2471         
2472           linklist_free(group_base);
2473           group_base = NULL;
2474           group_count = 0;
2475         }
2476     }
2477
2478   group_count = 0;
2479   group_base = NULL;
2480
2481   if (rc = ad_get_group(ldap_handle, dn_path, before_group_name, 
2482                         before_group_membership, 
2483                         MoiraId, "samAccountName", &group_base, 
2484                         &group_count, filter))
2485     return(rc);
2486
2487   if (group_count == 0)
2488     {
2489       return(AD_NO_GROUPS_FOUND);
2490     }
2491
2492   if (group_count != 1)
2493     {
2494       com_err(whoami, 0, "Unable to process multiple groups with "
2495               "MoiraId = %s exist in the directory", MoiraId);
2496       return(AD_MULTIPLE_GROUPS_FOUND);
2497     }
2498
2499   strcpy(old_dn, group_base->dn);
2500
2501   linklist_free(group_base);
2502   group_base = NULL;
2503   group_count = 0;
2504   attr_array[0] = "sAMAccountName";
2505   attr_array[1] = NULL;
2506
2507   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
2508                            &group_base, &group_count, 
2509                            LDAP_SCOPE_SUBTREE)) != 0)
2510     {
2511       com_err(whoami, 0, "Unable to get list %s dn : %s",
2512               after_group_name, ldap_err2string(rc));
2513       return(rc);
2514     }
2515
2516   if (group_count != 1)
2517     {
2518       com_err(whoami, 0,
2519               "Unable to get sAMAccountName for group %s", 
2520               before_group_name);
2521       return(AD_LDAP_FAILURE);
2522     }
2523   
2524   strcpy(sam_name, group_base->value);
2525   linklist_free(group_base);
2526   group_base = NULL;
2527   group_count = 0;
2528   
2529   sprintf(new_dn_path, "%s,%s", after_group_ou, dn_path);
2530   sprintf(new_dn, "cn=%s", after_group_name);
2531   sprintf(mail, "%s@%s", after_group_name, lowercase(ldap_domain));
2532   sprintf(contact_mail, "%s@mit.edu", after_group_name); 
2533   sprintf(proxy_address, "SMTP:%s@%s", after_group_name, 
2534           lowercase(ldap_domain));
2535   sprintf(mail_nickname, "%s", after_group_name);
2536
2537   com_err(whoami, 0, "Old %s New %s,%s", old_dn, new_dn, new_dn_path);
2538
2539   if ((rc = ldap_rename_s(ldap_handle, old_dn, new_dn, new_dn_path,
2540                               TRUE, NULL, NULL)) != LDAP_SUCCESS)
2541     {
2542       com_err(whoami, 0, "Unable to rename list from %s to %s : %s",
2543               before_group_name, after_group_name, ldap_err2string(rc));
2544       return(rc);
2545     }
2546   
2547   name_v[0] = after_group_name;
2548
2549   if (!strncmp(&sam_name[strlen(sam_name) - strlen(group_suffix)], 
2550                group_suffix, strlen(group_suffix)))
2551     {
2552       sprintf(sam_name, "%s%s", after_group_name, group_suffix);
2553     }
2554   else
2555     {
2556       com_err(whoami, 0, 
2557               "Unable to rename list from %s to %s : sAMAccountName not found",
2558               before_group_name, after_group_name);
2559       return(rc);
2560     }
2561
2562   samAccountName_v[0] = sam_name;
2563
2564   if (after_security_flag)
2565     groupTypeControl |= ADS_GROUP_TYPE_SECURITY_ENABLED;
2566
2567   sprintf(groupTypeControlStr, "%ld", groupTypeControl);
2568   groupTypeControl_v[0] = groupTypeControlStr;
2569   mitMoiraId_v[0] = MoiraId;
2570
2571   sprintf(new_dn, "cn=%s,%s,%s", after_group_name, after_group_ou, dn_path);
2572   rc = attribute_update(ldap_handle, new_dn, after_desc, "description", 
2573                         after_group_name);
2574   n = 0;
2575   ADD_ATTR("samAccountName", samAccountName_v, LDAP_MOD_REPLACE);
2576   ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
2577   ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
2578   ADD_ATTR("groupType", groupTypeControl_v, LDAP_MOD_REPLACE);
2579
2580   if(!ActiveDirectory) 
2581     {
2582       ADD_ATTR("name", name_v, LDAP_MOD_REPLACE);
2583     }
2584
2585   if (Exchange)
2586     {
2587       if(atoi(maillist) && !MailDisabled && email_isvalid(mail)) 
2588         {
2589           mail_nickname_v[0] = mail_nickname;
2590           proxy_address_v[0] = proxy_address;
2591           mail_v[0] = mail;
2592           report_to_originator_v[0] = "TRUE";
2593
2594           ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_REPLACE);
2595           ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
2596           ADD_ATTR("proxyAddresses", proxy_address_v, LDAP_MOD_REPLACE);
2597           ADD_ATTR("reportToOriginator", report_to_originator_v, 
2598                    LDAP_MOD_REPLACE);
2599         } 
2600       else 
2601         {
2602           mail_nickname_v[0] = NULL;
2603           proxy_address_v[0] = NULL;
2604           mail_v[0] = NULL;
2605           legacy_exchange_dn_v[0] = NULL;
2606           address_book_v[0] = NULL;
2607           report_to_originator_v[0] = NULL;
2608
2609           ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_REPLACE);
2610           ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
2611           ADD_ATTR("proxyAddresses", proxy_address_v, LDAP_MOD_REPLACE);
2612           ADD_ATTR("legacyExchangeDN", legacy_exchange_dn_v, LDAP_MOD_REPLACE);
2613           ADD_ATTR("showInAddressBook", address_book_v, LDAP_MOD_REPLACE);
2614           ADD_ATTR("reportToOriginator", report_to_originator_v, 
2615                    LDAP_MOD_REPLACE);
2616         }
2617     }
2618   else
2619     {
2620       if(atoi(maillist) && email_isvalid(contact_mail)) 
2621         {
2622           mail_v[0] = contact_mail;
2623           ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
2624
2625           if(!ActiveDirectory)
2626             {
2627               null_v[0] = "/dev/null";
2628               ADD_ATTR("mailRoutingAddress", null_v, LDAP_MOD_REPLACE);
2629             }
2630         }
2631     }
2632
2633   mods[n] = NULL;
2634
2635   if ((rc = ldap_modify_s(ldap_handle, new_dn, mods)) != LDAP_SUCCESS)
2636     {
2637       com_err(whoami, 0, 
2638               "Unable to modify list data for %s after renaming: %s",
2639               after_group_name, ldap_err2string(rc));
2640     }
2641
2642   for (i = 0; i < n; i++)
2643     free(mods[i]);
2644
2645   return(rc);
2646 }
2647
2648 int group_create(int ac, char **av, void *ptr)
2649 {
2650   LDAPMod *mods[20];
2651   char new_dn[256];
2652   char group_ou[256];
2653   char new_group_name[256];
2654   char sam_group_name[256];
2655   char cn_group_name[256];
2656   char mail[256];
2657   char contact_mail[256];
2658   char mail_nickname[256];
2659   char proxy_address[256];
2660   char address_book[256];
2661   char *cn_v[] = {NULL, NULL};
2662   char *objectClass_v[] = {"top", "group", NULL};
2663   char *objectClass_ldap_v[] = {"top", "microsoftComTop", "securityPrincipal",
2664                                 "group", "mailRecipient", NULL};
2665   char info[256];
2666   char *samAccountName_v[] = {NULL, NULL};
2667   char *altSecurityIdentities_v[] = {NULL, NULL};
2668   char *member_v[] = {NULL, NULL};
2669   char *name_v[] = {NULL, NULL};
2670   char *desc_v[] = {NULL, NULL};
2671   char *info_v[] = {NULL, NULL};
2672   char *mitMoiraId_v[] = {NULL, NULL};
2673   char *mitMoiraPublic_v[] = {NULL, NULL};
2674   char *mitMoiraHidden_v[] = {NULL, NULL};
2675   char *groupTypeControl_v[] = {NULL, NULL};
2676   char *mail_v[] = {NULL, NULL};
2677   char *proxy_address_v[] = {NULL, NULL};
2678   char *mail_nickname_v[] = {NULL, NULL};
2679   char *report_to_originator_v[] = {NULL, NULL};
2680   char *address_book_v[] = {NULL, NULL};
2681   char *legacy_exchange_dn_v[] = {NULL, NULL};
2682   char *gidNumber_v[] = {NULL, NULL};
2683   char *null_v[] = {NULL, NULL};
2684   char groupTypeControlStr[80];
2685   char group_membership[1];
2686   int  i;
2687   int  security_flag;
2688   u_int groupTypeControl;
2689   int  n;
2690   int  rc;
2691   int  updateGroup;
2692   int  MailDisabled = 0;
2693   char **call_args;
2694   LK_ENTRY *group_base;
2695   int  group_count;
2696   char filter[1024];
2697   char *attr_array[3];
2698   
2699   call_args = ptr;
2700
2701   if(UseGroupUniversal)
2702     groupTypeControl = ADS_GROUP_TYPE_UNIVERSAL_GROUP;
2703   else 
2704     groupTypeControl = ADS_GROUP_TYPE_GLOBAL_GROUP;
2705
2706   if (!check_string(av[L_NAME]))
2707     {
2708       com_err(whoami, 0, "Unable to process invalid LDAP list name %s", 
2709               av[L_NAME]);
2710       return(AD_INVALID_NAME);
2711     }
2712
2713   updateGroup = (int)call_args[4];
2714   memset(group_ou, 0, sizeof(group_ou));
2715   memset(group_membership, 0, sizeof(group_membership));
2716   security_flag = 0;
2717
2718   get_group_membership(group_membership, group_ou, &security_flag, av);
2719
2720   strcpy(new_group_name, av[L_NAME]);
2721   sprintf(new_dn, "cn=%s,%s,%s", new_group_name, group_ou, call_args[1]);
2722   sprintf(contact_mail, "%s@mit.edu", av[L_NAME]);
2723   sprintf(mail, "%s@%s", av[L_NAME], lowercase(ldap_domain));
2724   sprintf(mail_nickname, "%s", av[L_NAME]);
2725
2726   if (security_flag)
2727     groupTypeControl |= ADS_GROUP_TYPE_SECURITY_ENABLED;
2728   
2729   sprintf(sam_group_name, "%s%s", av[L_NAME], group_suffix);
2730
2731   if (!updateGroup)
2732     {
2733       sprintf(groupTypeControlStr, "%ld", groupTypeControl);
2734       groupTypeControl_v[0] = groupTypeControlStr;
2735
2736       strcpy(cn_group_name, av[L_NAME]);
2737       
2738       samAccountName_v[0] = sam_group_name;
2739       name_v[0] = new_group_name;
2740       cn_v[0] = new_group_name;
2741
2742       n = 0;
2743       ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
2744
2745       if(ActiveDirectory)
2746         {
2747           ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2748         } 
2749       else
2750         {
2751           mitMoiraPublic_v[0] = av[L_PUBLIC];
2752           mitMoiraHidden_v[0] = av[L_HIDDEN];
2753           ADD_ATTR("objectClass", objectClass_ldap_v, LDAP_MOD_ADD);
2754           ADD_ATTR("mitMoiraPublic", mitMoiraPublic_v, LDAP_MOD_ADD);
2755           ADD_ATTR("mitMoiraHidden", mitMoiraHidden_v, LDAP_MOD_ADD);
2756           
2757           if(atoi(av[L_GROUP])) 
2758             {
2759               gidNumber_v[0] = av[L_GID];
2760               ADD_ATTR("gidNumber", gidNumber_v, LDAP_MOD_ADD);
2761             }
2762         }
2763
2764       ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
2765       ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2766       ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2767
2768       if (Exchange)
2769         {
2770           if(atoi(av[L_MAILLIST])) 
2771             {
2772               group_count = 0;
2773               group_base = NULL;
2774               
2775               sprintf(filter, "(&(objectClass=user)(cn=%s))", av[L_NAME]);
2776               attr_array[0] = "cn";
2777               attr_array[1] = NULL;
2778               
2779               if ((rc = linklist_build((LDAP *)call_args[0], call_args[1], 
2780                                        filter, attr_array, &group_base, 
2781                                        &group_count,
2782                                        LDAP_SCOPE_SUBTREE)) != 0)
2783                 {
2784                   com_err(whoami, 0, "Unable to process group %s : %s",
2785                           av[L_NAME], ldap_err2string(rc));
2786                   return(rc);
2787                 }
2788               
2789               if (group_count)
2790                 {
2791                   com_err(whoami, 0, "Object already exists with name %s",
2792                           av[L_NAME]);
2793                   MailDisabled++;
2794                 }
2795         
2796               linklist_free(group_base);
2797               group_base = NULL;
2798               group_count = 0;
2799             }
2800           
2801           if(atoi(av[L_MAILLIST]) && !MailDisabled && email_isvalid(mail)) 
2802             {
2803               mail_nickname_v[0] = mail_nickname;
2804               report_to_originator_v[0] = "TRUE";
2805
2806               ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_ADD);
2807               ADD_ATTR("reportToOriginator", report_to_originator_v, 
2808                        LDAP_MOD_ADD);
2809             }
2810         }
2811       else
2812         {
2813           if(atoi(av[L_MAILLIST]) && email_isvalid(contact_mail)) 
2814             {
2815               mail_v[0] = contact_mail;
2816               ADD_ATTR("mail", mail_v, LDAP_MOD_ADD);
2817
2818               if(!ActiveDirectory)
2819                 {
2820                   null_v[0] = "/dev/null";
2821                   ADD_ATTR("mailRoutingAddress", null_v, LDAP_MOD_ADD);
2822                 }
2823             }
2824         }
2825       
2826       if (strlen(av[L_DESC]) != 0)
2827         {
2828           desc_v[0] = av[L_DESC];
2829           ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2830         }
2831       
2832       ADD_ATTR("groupType", groupTypeControl_v, LDAP_MOD_ADD);
2833
2834       if (strlen(av[L_ACE_NAME]) != 0)
2835         {
2836           sprintf(info, "The Administrator of this list is: %s", 
2837                   av[L_ACE_NAME]);
2838           info_v[0] = info;
2839           ADD_ATTR("info", info_v, LDAP_MOD_ADD);
2840         }
2841
2842       if (strlen(call_args[5]) != 0)
2843         {
2844           mitMoiraId_v[0] = call_args[5];
2845           ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_ADD);
2846         }
2847           
2848       mods[n] = NULL;
2849       
2850       rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
2851       
2852       for (i = 0; i < n; i++)
2853         free(mods[i]);
2854
2855       if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2856         {
2857           com_err(whoami, 0, "Unable to create list %s in directory : %s",
2858                   av[L_NAME], ldap_err2string(rc));
2859           callback_rc = rc;
2860           return(rc);
2861         }
2862     }
2863
2864   if ((rc == LDAP_ALREADY_EXISTS) || (updateGroup))
2865     {
2866       rc = attribute_update((LDAP *)call_args[0], new_dn, av[L_DESC], 
2867                             "description", av[L_NAME]);
2868       sprintf(info, "The Administrator of this list is: %s", av[L_ACE_NAME]);
2869
2870       rc = attribute_update((LDAP *)call_args[0], new_dn, info, "info", 
2871                                 av[L_NAME]);
2872
2873       n = 0;
2874
2875       if (strlen(call_args[5]) != 0)
2876         {
2877           mitMoiraId_v[0] = call_args[5];
2878           ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
2879         }
2880
2881       if (!(atoi(av[L_ACTIVE])))
2882         {
2883           member_v[0] = NULL;
2884           ADD_ATTR("member", member_v, LDAP_MOD_REPLACE);
2885         }
2886    
2887       if (!ActiveDirectory) 
2888         {
2889           mitMoiraPublic_v[0] = av[L_PUBLIC];
2890           mitMoiraHidden_v[0] = av[L_HIDDEN];
2891           ADD_ATTR("mitMoiraPublic", mitMoiraPublic_v, LDAP_MOD_REPLACE);
2892           ADD_ATTR("mitMoiraHidden", mitMoiraHidden_v, LDAP_MOD_REPLACE);
2893
2894           if(atoi(av[L_GROUP])) 
2895             {
2896               gidNumber_v[0] = av[L_GID];
2897               ADD_ATTR("gidNumber", gidNumber_v, LDAP_MOD_REPLACE);
2898             }
2899           else
2900             {
2901               ADD_ATTR("gidNumber", gidNumber_v, LDAP_MOD_REPLACE);
2902             }
2903         }
2904
2905       if (Exchange)
2906         {
2907           if(atoi(av[L_MAILLIST])) 
2908             {
2909               group_count = 0;
2910               group_base = NULL;
2911               
2912               sprintf(filter, "(&(objectClass=user)(cn=%s))", av[L_NAME]);
2913               attr_array[0] = "cn";
2914               attr_array[1] = NULL;
2915               
2916               if ((rc = linklist_build((LDAP *)call_args[0], call_args[1], 
2917                                        filter, attr_array, &group_base, 
2918                                        &group_count,
2919                                        LDAP_SCOPE_SUBTREE)) != 0)
2920                 {
2921                   com_err(whoami, 0, "Unable to process group %s : %s",
2922                           av[L_NAME], ldap_err2string(rc));
2923                   return(rc);
2924                 }
2925               
2926               if (group_count)
2927                 {
2928                   com_err(whoami, 0, "Object already exists with name %s",
2929                           av[L_NAME]);
2930                   MailDisabled++;
2931                 }
2932               
2933               linklist_free(group_base);
2934               group_base = NULL;
2935               group_count = 0;
2936             }
2937
2938           if (atoi(av[L_MAILLIST]) && !MailDisabled && email_isvalid(mail)) 
2939             {
2940               mail_nickname_v[0] = mail_nickname;
2941               report_to_originator_v[0] = "TRUE";
2942
2943               ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_REPLACE);
2944               ADD_ATTR("reportToOriginator", report_to_originator_v, 
2945                        LDAP_MOD_REPLACE);
2946             }
2947           else 
2948             {
2949               mail_v[0] = NULL;
2950               mail_nickname_v[0] = NULL;
2951               proxy_address_v[0] = NULL;
2952               legacy_exchange_dn_v[0] = NULL;
2953               address_book_v[0] = NULL;
2954               report_to_originator_v[0] = NULL;
2955
2956               ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_REPLACE);
2957               ADD_ATTR("proxyAddresses", proxy_address_v, LDAP_MOD_REPLACE);
2958               ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
2959               ADD_ATTR("legacyExchangeDN", legacy_exchange_dn_v, 
2960                        LDAP_MOD_REPLACE);
2961               ADD_ATTR("showInAddressBook", address_book_v, LDAP_MOD_REPLACE);
2962               ADD_ATTR("reportToOriginator", report_to_originator_v, 
2963                        LDAP_MOD_REPLACE);
2964             }
2965         }
2966       else
2967         {
2968           if (atoi(av[L_MAILLIST]) && email_isvalid(contact_mail)) 
2969             {
2970               mail_v[0] = contact_mail;
2971               ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
2972
2973               if(!ActiveDirectory)
2974                 {
2975                   null_v[0] = "/dev/null";
2976                   ADD_ATTR("mailRoutingAddress", null_v, LDAP_MOD_REPLACE);
2977                 }
2978             }
2979           else
2980             {
2981               mail_v[0] = NULL;
2982               ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
2983
2984               if(!ActiveDirectory)
2985                 {
2986                   null_v[0] = NULL;
2987                   ADD_ATTR("mailRoutingAddress", null_v, LDAP_MOD_REPLACE);
2988                 }
2989             }
2990         }
2991    
2992       mods[n] = NULL;
2993       rc = LDAP_SUCCESS;
2994
2995       if (n != 0)
2996         {
2997           rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
2998
2999           for (i = 0; i < n; i++)
3000               free(mods[i]);
3001
3002           if (rc != LDAP_SUCCESS)
3003             {
3004               com_err(whoami, 0, "Unable to update list %s in directory : %s",
3005                       av[L_NAME], ldap_err2string(rc));
3006               callback_rc = rc;
3007               return(rc);
3008             }
3009         }
3010     }
3011
3012   ProcessGroupSecurity((LDAP *)call_args[0], call_args[1], av[L_NAME], 
3013                        atoi(av[L_HIDDEN]),  av[L_ACE_TYPE], av[L_ACE_NAME]);
3014
3015   return(LDAP_SUCCESS);
3016 }
3017
3018 int ProcessGroupSecurity(LDAP *ldap_handle, char *dn_path, 
3019                          char *TargetGroupName, int HiddenGroup, 
3020                          char *AceType, char *AceName)
3021 {
3022   char          filter_exp[1024];
3023   char          *attr_array[5];
3024   char          search_path[512];
3025   char          root_ou[128];
3026   char          TemplateDn[512];
3027   char          TemplateSamName[128];
3028   char          TargetDn[512];
3029   char          TargetSamName[128];
3030   char          AceSamAccountName[128];
3031   char          AceDn[256];
3032   unsigned char AceSid[128];
3033   unsigned char UserTemplateSid[128];
3034   char          acBERBuf[N_SD_BER_BYTES];
3035   char          GroupSecurityTemplate[256];
3036   char          hide_addres_lists[256];
3037   char          address_book[256];
3038   char          *hide_address_lists_v[] = {NULL, NULL};
3039   char          *address_book_v[] = {NULL, NULL};
3040   char          *owner_v[] = {NULL, NULL};
3041   int           AceSidCount;
3042   int           UserTemplateSidCount;
3043   int           group_count;
3044   int           n;
3045   int           i;
3046   int           rc;
3047   int           nVal;
3048   ULONG         dwInfo;
3049   int           array_count = 0;
3050   LDAPMod       *mods[20];
3051   LK_ENTRY      *group_base;
3052   LDAP_BERVAL   **ppsValues;
3053   LDAPControl sControl = {"1.2.840.113556.1.4.801",
3054                           { N_SD_BER_BYTES, acBERBuf },
3055                           TRUE
3056                          };
3057   LDAPControl *apsServerControls[] = {&sControl, NULL};
3058   LDAPMessage *psMsg;
3059
3060   dwInfo = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | 
3061     DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;
3062   BEREncodeSecurityBits(dwInfo, acBERBuf);
3063
3064   sprintf(search_path, "%s,%s", group_ou_root, dn_path);
3065   sprintf(filter_exp, "(sAMAccountName=%s%s)", TargetGroupName, group_suffix);
3066   attr_array[0] = "sAMAccountName";
3067   attr_array[1] = NULL;
3068   group_count = 0;
3069   group_base = NULL;
3070
3071   if ((rc = linklist_build(ldap_handle, search_path, filter_exp, attr_array, 
3072                            &group_base, &group_count, 
3073                            LDAP_SCOPE_SUBTREE) != 0))
3074     return(1);
3075
3076   if (group_count != 1)
3077     {
3078       linklist_free(group_base);
3079       return(1);
3080     }
3081
3082   strcpy(TargetDn, group_base->dn);
3083   strcpy(TargetSamName, group_base->value);
3084   linklist_free(group_base);
3085   group_base = NULL;
3086   group_count = 0;
3087
3088   UserTemplateSidCount = 0;
3089   memset(UserTemplateSid, '\0', sizeof(UserTemplateSid));
3090   memset(AceSamAccountName, '\0', sizeof(AceSamAccountName));
3091   memset(AceSid, '\0', sizeof(AceSid));
3092   AceSidCount = 0;
3093   group_base = NULL;
3094   group_count = 0;
3095
3096   if (strlen(AceName) != 0)
3097     {
3098       if (!strcmp(AceType, "LIST"))
3099         {
3100           sprintf(AceSamAccountName, "%s%s", AceName, group_suffix);
3101           strcpy(root_ou, group_ou_root);
3102         }
3103       else if (!strcmp(AceType, "USER"))
3104         {
3105           sprintf(AceSamAccountName, "%s", AceName);
3106           strcpy(root_ou, user_ou);
3107         }
3108
3109       if (ActiveDirectory)
3110         {
3111           if (strlen(AceSamAccountName) != 0)
3112             {
3113               sprintf(search_path, "%s", dn_path);
3114               sprintf(filter_exp, "(sAMAccountName=%s)", AceSamAccountName);
3115               attr_array[0] = "objectSid";
3116               attr_array[1] = NULL;
3117               group_count = 0;
3118               group_base = NULL;
3119               
3120               if ((rc = linklist_build(ldap_handle, search_path, filter_exp, 
3121                                        attr_array, &group_base, &group_count, 
3122                                        LDAP_SCOPE_SUBTREE) != 0))
3123                 return(1);
3124               if (group_count == 1)
3125                 {
3126                   strcpy(AceDn, group_base->dn);
3127                   AceSidCount = group_base->length;
3128                   memcpy(AceSid, group_base->value, AceSidCount);
3129                 }
3130               linklist_free(group_base);
3131               group_base = NULL;
3132               group_count = 0;
3133             }
3134         }
3135       else
3136         {
3137           if (strlen(AceSamAccountName) != 0)
3138             {
3139               sprintf(search_path, "%s", dn_path);
3140               sprintf(filter_exp, "(sAMAccountName=%s)", AceSamAccountName);
3141               attr_array[0] = "samAccountName";
3142               attr_array[1] = NULL;
3143               group_count = 0;
3144               group_base = NULL;
3145               
3146               if ((rc = linklist_build(ldap_handle, search_path, filter_exp, 
3147                                        attr_array, &group_base, &group_count, 
3148                                        LDAP_SCOPE_SUBTREE) != 0))
3149                 return(1);
3150               if (group_count == 1)
3151                 {
3152                   strcpy(AceDn, group_base->dn);
3153                 }
3154               linklist_free(group_base);
3155               group_base = NULL;
3156               group_count = 0;
3157             }
3158         }
3159     }
3160
3161   if (!ActiveDirectory) 
3162     {
3163       if (strlen(AceDn) != 0) 
3164         {
3165           owner_v[0] = strdup(AceDn);
3166           n = 0;
3167           ADD_ATTR("owner", owner_v, LDAP_MOD_REPLACE);
3168
3169           mods[n] = NULL;
3170
3171           rc = ldap_modify_s(ldap_handle, TargetDn, mods);
3172           
3173           for (i = 0; i < n; i++)
3174             free(mods[i]);
3175
3176           if (rc != LDAP_SUCCESS)
3177             com_err(whoami, 0, "Unable to set owner for group %s : %s",
3178               TargetGroupName, ldap_err2string(rc));
3179         }
3180
3181       return(rc);
3182     }
3183   
3184   if (AceSidCount == 0)
3185     {
3186       com_err(whoami, 0, "Group %s: Administrator: %s, Type: %s - does not "
3187               "have a directory SID.", TargetGroupName, AceName, AceType);
3188       com_err(whoami, 0, "   Non-admin security group template will be used.");
3189     }
3190   else
3191     {
3192       sprintf(search_path, "%s,%s", security_template_ou, dn_path);
3193       sprintf(filter_exp, "(sAMAccountName=%s)", "UserTemplate.u");
3194       attr_array[0] = "objectSid";
3195       attr_array[1] = NULL;
3196
3197       group_count = 0;
3198       group_base = NULL;
3199
3200       if ((rc = linklist_build(ldap_handle, search_path, filter_exp, 
3201                                attr_array, &group_base, &group_count, 
3202                                LDAP_SCOPE_SUBTREE) != 0))
3203         return(1);
3204
3205       if ((rc != 0) || (group_count != 1))
3206         {
3207           com_err(whoami, 0, "Unable to process user security template: %s", 
3208                   "UserTemplate");
3209           AceSidCount = 0;
3210         }
3211       else
3212         {
3213           UserTemplateSidCount = group_base->length;
3214           memcpy(UserTemplateSid, group_base->value, UserTemplateSidCount);
3215         }
3216       linklist_free(group_base);
3217       group_base = NULL;
3218       group_count = 0;
3219     }
3220
3221   if (HiddenGroup)
3222     {
3223       if (AceSidCount == 0)
3224         {
3225           strcpy(GroupSecurityTemplate, HIDDEN_GROUP);
3226           sprintf(filter_exp, "(sAMAccountName=%s)", HIDDEN_GROUP);
3227         }
3228       else
3229         {
3230           strcpy(GroupSecurityTemplate, HIDDEN_GROUP_WITH_ADMIN);
3231           sprintf(filter_exp, "(sAMAccountName=%s)", HIDDEN_GROUP_WITH_ADMIN);
3232         }
3233     }
3234   else
3235     {
3236       if (AceSidCount == 0)
3237         {
3238           strcpy(GroupSecurityTemplate, NOT_HIDDEN_GROUP);
3239           sprintf(filter_exp, "(sAMAccountName=%s)", NOT_HIDDEN_GROUP);
3240         }
3241       else
3242         {
3243           strcpy(GroupSecurityTemplate, NOT_HIDDEN_GROUP_WITH_ADMIN);
3244           sprintf(filter_exp, "(sAMAccountName=%s)", 
3245                   NOT_HIDDEN_GROUP_WITH_ADMIN);
3246         }
3247     }
3248
3249   sprintf(search_path, "%s,%s", security_template_ou, dn_path);
3250   attr_array[0] = "sAMAccountName";
3251   attr_array[1] = NULL;
3252   group_count = 0;
3253   group_base = NULL;
3254
3255   if ((rc = linklist_build(ldap_handle, search_path, filter_exp, attr_array, 
3256                            &group_base, &group_count, 
3257                            LDAP_SCOPE_SUBTREE) != 0))
3258     return(1);
3259
3260   if (group_count != 1)
3261     {
3262       linklist_free(group_base);
3263       com_err(whoami, 0, "Unable to process group security template: %s - "
3264               "security not set", GroupSecurityTemplate);
3265       return(1);
3266     }
3267
3268   strcpy(TemplateDn, group_base->dn);
3269   strcpy(TemplateSamName, group_base->value);
3270   linklist_free(group_base);
3271   group_base = NULL;
3272   group_count = 0;
3273   
3274   sprintf(filter_exp, "(sAMAccountName=%s)", TemplateSamName);
3275   rc = ldap_search_ext_s(ldap_handle,
3276                          TemplateDn,
3277                          LDAP_SCOPE_SUBTREE,
3278                          filter_exp,
3279                          NULL,
3280                          0,
3281                          apsServerControls,
3282                          NULL,
3283                          NULL,
3284                          0,
3285                          &psMsg);
3286
3287   if ((psMsg = ldap_first_entry(ldap_handle, psMsg)) == NULL)
3288     {
3289       com_err(whoami, 0, "Unable to find group security template: %s - "
3290               "security not set", GroupSecurityTemplate);
3291       return(1);
3292     }
3293
3294   ppsValues = ldap_get_values_len(ldap_handle, psMsg, "ntSecurityDescriptor");
3295
3296   if (ppsValues == NULL)
3297     {
3298       com_err(whoami, 0, "Unable to find group security descriptor for group "
3299               "%s - security not set", GroupSecurityTemplate);
3300       return(1);
3301     }
3302   
3303   if (AceSidCount != 0)
3304     {
3305       for (nVal = 0; ppsValues[nVal] != NULL; nVal++)
3306         {
3307           for (i = 0; 
3308                i < (int)(ppsValues[nVal]->bv_len - UserTemplateSidCount); i++)
3309             {
3310               if (!memcmp(&ppsValues[nVal]->bv_val[i], UserTemplateSid, 
3311                           UserTemplateSidCount))
3312                 {
3313                   memcpy(&ppsValues[nVal]->bv_val[i], AceSid, AceSidCount);
3314                   break;
3315                 }
3316             }
3317         }
3318     }
3319
3320   n = 0;
3321   ADD_ATTR("ntSecurityDescriptor", (char **)ppsValues, 
3322            LDAP_MOD_REPLACE | LDAP_MOD_BVALUES);
3323
3324   if (Exchange)
3325     {
3326       if(HiddenGroup) 
3327         {
3328           hide_address_lists_v[0] = "TRUE";
3329           address_book_v[0] = NULL;
3330           ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v, 
3331                    LDAP_MOD_REPLACE);
3332           ADD_ATTR("showInAddressBook", address_book_v, LDAP_MOD_REPLACE);
3333         } else {
3334           hide_address_lists_v[0] = NULL;
3335           ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v, 
3336                    LDAP_MOD_REPLACE);
3337         }
3338     }
3339
3340   mods[n] = NULL;
3341
3342   rc = ldap_modify_s(ldap_handle, TargetDn, mods);
3343
3344   for (i = 0; i < n; i++)
3345     free(mods[i]);
3346
3347   ldap_value_free_len(ppsValues);
3348   ldap_msgfree(psMsg);
3349
3350   if (rc != LDAP_SUCCESS)
3351     {
3352       com_err(whoami, 0, "Unable to set security settings for group %s : %s",
3353               TargetGroupName, ldap_err2string(rc));
3354
3355       if (AceSidCount != 0)
3356         {
3357           com_err(whoami, 0, 
3358                   "Trying to set security for group %s without admin.",
3359                   TargetGroupName);
3360
3361           if (rc = ProcessGroupSecurity(ldap_handle, dn_path, TargetGroupName, 
3362                                         HiddenGroup, "", ""))
3363             {
3364               com_err(whoami, 0, "Unable to set security for group %s.",
3365                       TargetGroupName);
3366               return(rc);
3367             }
3368         }
3369       return(rc);
3370     }
3371
3372   return(rc);
3373 }
3374
3375 int group_delete(LDAP *ldap_handle, char *dn_path, char *group_name, 
3376                  char *group_membership, char *MoiraId)
3377 {
3378   LK_ENTRY  *group_base;
3379   char      temp[512];
3380   char      filter[128];
3381   int       group_count;
3382   int       rc;
3383
3384   if (!check_string(group_name))
3385     {
3386       com_err(whoami, 0, 
3387               "Unable to process invalid LDAP list name %s", group_name);
3388       return(AD_INVALID_NAME);
3389     }
3390
3391   memset(filter, '\0', sizeof(filter));
3392   group_count = 0;
3393   group_base = NULL;
3394   sprintf(temp, "%s,%s", group_ou_root, dn_path);
3395
3396   if (rc = ad_get_group(ldap_handle, temp, group_name, 
3397                         group_membership, MoiraId, 
3398                         "samAccountName", &group_base, 
3399                         &group_count, filter))
3400     return(rc);
3401
3402   if (group_count == 1)
3403     {
3404       if ((rc = ldap_delete_s(ldap_handle, group_base->dn)) != LDAP_SUCCESS)
3405         {
3406           linklist_free(group_base);
3407           com_err(whoami, 0, "Unable to delete list %s from directory : %s",
3408                   group_name, ldap_err2string(rc));
3409           return(rc);
3410         }
3411       linklist_free(group_base);
3412     }
3413   else
3414     {
3415       linklist_free(group_base);
3416       com_err(whoami, 0, "Unable to find list %s in directory.", group_name);
3417       return(AD_NO_GROUPS_FOUND);
3418     }
3419   
3420   return(0);
3421 }
3422
3423 int BEREncodeSecurityBits(ULONG uBits, char *pBuffer)
3424 {
3425     *pBuffer++ = 0x30;
3426     *pBuffer++ = 0x03;
3427     *pBuffer++ = 0x02;
3428     *pBuffer++ = 0x00;
3429     return(N_SD_BER_BYTES);
3430 }
3431
3432 int process_lists(int ac, char **av, void *ptr)
3433 {
3434   int   rc;
3435   int   security_flag;
3436   char  group_ou[256];
3437   char  group_membership[2];
3438   char  **call_args;
3439
3440   call_args = ptr;
3441
3442   security_flag = 0;
3443   memset(group_ou, '\0', sizeof(group_ou));
3444   memset(group_membership, '\0', sizeof(group_membership));
3445   get_group_membership(group_membership, group_ou, &security_flag, av);
3446   rc = populate_group((LDAP *)call_args[0], (char *)call_args[1], 
3447                       av[L_NAME], group_ou, group_membership, 
3448                       security_flag, "");
3449
3450   return(0);
3451 }
3452
3453 int member_list_build(int ac, char **av, void *ptr)
3454 {
3455   LK_ENTRY  *linklist;
3456   char      temp[1024];
3457   char      **call_args;
3458   char      *s;
3459   call_args = ptr;
3460
3461   strcpy(temp, av[ACE_NAME]);
3462   StringTrim(temp);
3463   
3464   if (!check_string(temp))
3465     return(0);
3466
3467   if (!strcmp(av[ACE_TYPE], "USER"))
3468     {
3469       if (!((int)call_args[3] & MOIRA_USERS))
3470         return(0);
3471     }
3472   else if (!strcmp(av[ACE_TYPE], "STRING"))
3473     {
3474       if (Exchange)
3475         {
3476           if((s = strchr(temp, '@')) == (char *) NULL) 
3477             {
3478               strcat(temp, "@mit.edu");
3479             }
3480           
3481           if(!strncasecmp(&temp[strlen(temp) - 6], ".LOCAL", 6))
3482             {
3483               s = strrchr(temp, '.');
3484               *s = '\0';
3485               strcat(s, ".mit.edu");
3486             }
3487         }
3488
3489       if (!((int)call_args[3] & MOIRA_STRINGS))
3490         return(0);
3491         
3492       if (contact_create((LDAP *)call_args[0], call_args[1], temp, contact_ou))
3493         return(0);
3494     }
3495   else if (!strcmp(av[ACE_TYPE], "LIST"))
3496     {
3497       if (!((int)call_args[3] & MOIRA_LISTS))
3498         return(0);
3499     }
3500   else if (!strcmp(av[ACE_TYPE], "KERBEROS"))
3501     {
3502       if (!((int)call_args[3] & MOIRA_KERBEROS))
3503         return(0);
3504
3505       if (contact_create((LDAP *)call_args[0], call_args[1], temp, 
3506                          kerberos_ou))
3507         return(0);
3508
3509     }
3510   else if (!strcmp(av[ACE_TYPE], "MACHINE"))
3511     {
3512       if (!((int)call_args[3] & MOIRA_MACHINE))
3513         return(0);
3514     }
3515   else
3516     return(0);
3517
3518   linklist = member_base;
3519
3520   while (linklist)
3521     {
3522     if (!strcasecmp(temp, linklist->member) &&
3523         !strcasecmp(av[ACE_TYPE], linklist->type))
3524       return(0);
3525
3526     linklist = linklist->next;
3527     }
3528
3529   linklist = calloc(1, sizeof(LK_ENTRY));
3530   linklist->op = 1;
3531   linklist->dn = NULL;
3532   linklist->list = calloc(1, strlen(call_args[2]) + 1);
3533   strcpy(linklist->list, call_args[2]);
3534   linklist->type = calloc(1, strlen(av[ACE_TYPE]) + 1);
3535   strcpy(linklist->type, av[ACE_TYPE]);
3536   linklist->member = calloc(1, strlen(temp) + 1);
3537   strcpy(linklist->member, temp);
3538   linklist->next = member_base;
3539   member_base = linklist;
3540
3541   return(0);
3542 }
3543
3544 int member_remove(LDAP *ldap_handle, char *dn_path, char *group_name, 
3545                   char *group_ou, char *group_membership, char *user_name,
3546                   char *UserOu, char *MoiraId)
3547 {
3548   char        distinguished_name[1024];
3549   char        *modvalues[2];
3550   char        temp[256];
3551   char        filter[128];
3552   char        *attr_array[3];
3553   int         group_count;
3554   int         i;
3555   int         n;
3556   LDAPMod     *mods[20];
3557   LK_ENTRY    *group_base;
3558   ULONG       rc;
3559   char        *s;
3560
3561   if (!check_string(group_name))
3562     return(AD_INVALID_NAME);
3563
3564   memset(filter, '\0', sizeof(filter));
3565   group_base = NULL;
3566   group_count = 0;
3567
3568   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
3569                         group_membership, MoiraId, 
3570                         "samAccountName", &group_base, 
3571                         &group_count, filter))
3572     return(rc);
3573
3574   if (group_count != 1)
3575     {
3576       com_err(whoami, 0, "Unable to find list %s in directory",
3577               group_name);
3578       linklist_free(group_base);
3579       group_base = NULL;
3580       group_count = 0;
3581       goto cleanup;
3582     }
3583
3584   strcpy(distinguished_name, group_base->dn);
3585   linklist_free(group_base);
3586   group_base = NULL;
3587   group_count = 0;
3588
3589   if(ActiveDirectory)
3590     {
3591       sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
3592     }
3593   else
3594     {
3595       if(!strcmp(UserOu, user_ou))
3596         sprintf(temp, "uid=%s,%s,%s", user_name, UserOu, dn_path);
3597       else
3598         sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
3599     }
3600
3601   modvalues[0] = temp;
3602   modvalues[1] = NULL;
3603
3604   n = 0;
3605   ADD_ATTR("member", modvalues, LDAP_MOD_DELETE);
3606   mods[n] = NULL;
3607   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
3608
3609   for (i = 0; i < n; i++)
3610     free(mods[i]);
3611
3612   if (rc == LDAP_UNWILLING_TO_PERFORM)
3613     rc = LDAP_SUCCESS;
3614
3615   if (rc != LDAP_SUCCESS)
3616     {
3617       com_err(whoami, 0, "Unable to modify list %s members : %s",
3618               group_name, ldap_err2string(rc));
3619       goto cleanup;
3620     }
3621
3622   if ((!strcmp(UserOu, contact_ou)) || (!strcmp(UserOu, kerberos_ou))) 
3623     {
3624       if (Exchange)
3625         {
3626           if(!strcmp(UserOu, contact_ou) && 
3627              ((s = strstr(user_name, "@mit.edu")) != (char *) NULL))
3628             {
3629               memset(temp, '\0', sizeof(temp));
3630               strcpy(temp, user_name);
3631               s = strchr(temp, '@');
3632               *s = '\0';
3633               
3634               sprintf(filter, "(&(objectClass=user)(mailNickName=%s))", temp);
3635           
3636               if ((rc = linklist_build(ldap_handle, dn_path, filter, NULL,
3637                                        &group_base, &group_count, 
3638                                        LDAP_SCOPE_SUBTREE) != 0))
3639                 return(rc);       
3640               
3641               if(group_count)
3642                 goto cleanup;
3643               
3644               linklist_free(group_base);
3645               group_base = NULL;
3646               group_count = 0;
3647             }
3648           
3649           sprintf(filter, "(distinguishedName=%s)", temp);
3650           attr_array[0] = "memberOf";
3651           attr_array[1] = NULL;
3652           
3653           if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
3654                                    &group_base, &group_count, 
3655                                    LDAP_SCOPE_SUBTREE) != 0))
3656             return(rc);
3657           
3658
3659           if(!group_count) 
3660             {
3661               com_err(whoami, 0, "Removing unreferenced object %s", temp);
3662           
3663               if ((rc = ldap_delete_s(ldap_handle, temp)) != 0) 
3664                 return(rc);
3665             }
3666         }
3667     }
3668
3669  cleanup:
3670   return(rc);
3671 }
3672
3673 int member_add(LDAP *ldap_handle, char *dn_path, char *group_name, 
3674                char *group_ou, char *group_membership, char *user_name, 
3675                char *UserOu, char *MoiraId)
3676 {
3677   char        distinguished_name[1024];
3678   char        *modvalues[2];
3679   char        temp[256];
3680   char        filter[128];
3681   int         group_count;
3682   int         n;
3683   int         i;
3684   LDAPMod     *mods[20];
3685   LK_ENTRY    *group_base;
3686   ULONG       rc;
3687
3688   if (!check_string(group_name))
3689     return(AD_INVALID_NAME);
3690
3691   rc = 0;
3692   memset(filter, '\0', sizeof(filter));
3693   group_base = NULL;
3694   group_count = 0;
3695
3696   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
3697                         group_membership, MoiraId, 
3698                         "samAccountName", &group_base, 
3699                         &group_count, filter))
3700     return(rc);
3701
3702   if (group_count != 1)
3703     {
3704       linklist_free(group_base);
3705       group_base = NULL;
3706       group_count = 0;
3707       com_err(whoami, 0, "Unable to find list %s %d in directory",
3708               group_name, group_count);
3709       return(AD_MULTIPLE_GROUPS_FOUND);
3710     }
3711
3712   strcpy(distinguished_name, group_base->dn);
3713   linklist_free(group_base);
3714   group_base = NULL;
3715   group_count = 0;
3716
3717   if(ActiveDirectory)
3718     {
3719       sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
3720     }
3721   else 
3722     {
3723       if(!strcmp(UserOu, user_ou))
3724         sprintf(temp, "uid=%s,%s,%s", user_name, UserOu, dn_path);
3725       else
3726         sprintf(temp, "cn=%s,%s,%s", user_name, UserOu, dn_path);
3727     }
3728
3729   modvalues[0] = temp;
3730   modvalues[1] = NULL;
3731
3732   n = 0;
3733   ADD_ATTR("member", modvalues, LDAP_MOD_ADD);
3734   mods[n] = NULL;
3735   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
3736
3737   if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
3738     rc = LDAP_SUCCESS;
3739
3740   if ((!strcmp(UserOu, contact_ou)) || (!strcmp(UserOu, kerberos_ou)))
3741     {
3742       if (rc == LDAP_UNWILLING_TO_PERFORM)
3743         rc = LDAP_SUCCESS;
3744     }
3745
3746   for (i = 0; i < n; i++)
3747     free(mods[i]);
3748
3749   if (rc != LDAP_SUCCESS)
3750     {
3751       com_err(whoami, 0, "Unable to add %s to list %s as a member : %s",
3752               user_name, group_name, ldap_err2string(rc));
3753     }
3754
3755   return(rc);
3756 }
3757
3758 int contact_remove_email(LDAP *ld, char *bind_path,
3759                          LK_ENTRY **linklist_base, int linklist_current)
3760 {
3761   LK_ENTRY  *gPtr;
3762   int       rc;
3763   char      *mail_v[] = {NULL, NULL};
3764   LDAPMod   *mods[20];
3765   int n;
3766   int i;
3767
3768   mail_v[0] = NULL;
3769
3770   n = 0;
3771   ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
3772   ADD_ATTR("mailNickName", mail_v, LDAP_MOD_REPLACE);
3773   ADD_ATTR("proxyAddresses", mail_v, LDAP_MOD_REPLACE);
3774   ADD_ATTR("targetAddress", mail_v, LDAP_MOD_REPLACE);
3775   mods[n] = NULL;
3776
3777   gPtr = (*linklist_base);
3778   
3779   while(gPtr) {
3780     rc = ldap_modify_s(ld, gPtr->dn, mods);
3781     
3782     if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
3783       {
3784         com_err(whoami, 0, "Unable to modify contact %s in directory : %s",
3785                 gPtr->dn, ldap_err2string(rc));
3786         return(rc);
3787       }
3788
3789     gPtr = gPtr->next;
3790   }
3791
3792   for (i = 0; i < n; i++)
3793     free(mods[i]);
3794   
3795     return(rc);
3796 }
3797
3798 int contact_create(LDAP *ld, char *bind_path, char *user, char *group_ou)
3799 {
3800   LDAPMod *mods[20];
3801   LK_ENTRY  *group_base;
3802   int  group_count;
3803   char new_dn[256];
3804   char cn_user_name[256];
3805   char contact_name[256];
3806   char mail_nickname[256];
3807   char proxy_address_internal[256];
3808   char proxy_address_external[256];
3809   char target_address[256];
3810   char internal_contact_name[256];
3811   char filter[128];
3812   char mail[256];
3813   char principal[256];
3814   char mit_address_book[256];
3815   char default_address_book[256];
3816   char contact_address_book[256];
3817   char uid[256];
3818   char *email_v[] = {NULL, NULL};
3819   char *cn_v[] = {NULL, NULL};
3820   char *contact_v[] = {NULL, NULL};
3821   char *uid_v[] = {NULL, NULL};
3822   char *mail_nickname_v[] = {NULL, NULL};
3823   char *proxy_address_internal_v[] = {NULL, NULL};
3824   char *proxy_address_external_v[] = {NULL, NULL};
3825   char *target_address_v[] = {NULL, NULL};
3826   char *mit_address_book_v[] = {NULL, NULL};
3827   char *default_address_book_v[] = {NULL, NULL};
3828   char *contact_address_book_v[] = {NULL, NULL};
3829   char *hide_address_lists_v[] = {NULL, NULL};
3830   char *attr_array[3];
3831   char *objectClass_v[] = {"top", "person", 
3832                            "organizationalPerson", 
3833                            "contact", NULL};
3834   char *objectClass_ldap_v[] = {"top", "person", "microsoftComTop", 
3835                                 "inetOrgPerson", "organizationalPerson",
3836                                 "contact", "mailRecipient", "eduPerson",
3837                                 NULL};
3838   char *name_v[] = {NULL, NULL};
3839   char *desc_v[] = {NULL, NULL};
3840   char *s;
3841   int  n;
3842   int  rc;
3843   int  i;
3844   char temp[256];
3845   char *c;
3846   char *mail_routing_v[] = {NULL, NULL};
3847   char *principal_v[] = {NULL, NULL};
3848
3849   if (!check_string(user))
3850     {
3851       com_err(whoami, 0, "Unable to process invalid LDAP name %s", user);
3852       return(AD_INVALID_NAME);
3853     }
3854
3855   strcpy(mail, user);
3856   strcpy(contact_name, mail);
3857   strcpy(internal_contact_name, mail);
3858   
3859   if((s = strchr(internal_contact_name, '@')) != NULL) {
3860     *s = '?';
3861   }
3862
3863   sprintf(cn_user_name,"CN=%s,%s,%s", escape_string(contact_name), group_ou, 
3864           bind_path);
3865
3866   sprintf(target_address, "SMTP:%s", contact_name);
3867   sprintf(proxy_address_external, "SMTP:%s", contact_name);
3868   sprintf(mail_nickname, "%s", internal_contact_name);
3869  
3870   cn_v[0] = cn_user_name;
3871   contact_v[0] = contact_name;
3872   uid_v[0] = uid;
3873   name_v[0] = user;
3874   desc_v[0] = "Auto account created by Moira";
3875   email_v[0] = mail;
3876   proxy_address_internal_v[0] = proxy_address_internal;
3877   proxy_address_external_v[0] = proxy_address_external;
3878   mail_nickname_v[0] = mail_nickname;
3879   target_address_v[0] = target_address;
3880   mit_address_book_v[0] = mit_address_book;
3881   default_address_book_v[0] = default_address_book;
3882   contact_address_book_v[0] = contact_address_book;
3883   strcpy(new_dn, cn_user_name);
3884   n = 0;
3885
3886   ADD_ATTR("cn", contact_v, LDAP_MOD_ADD);
3887
3888   if(!ActiveDirectory)
3889     {
3890       if(!strcmp(group_ou, contact_ou))
3891         sprintf(uid, "%s%s", contact_name, "_strings");
3892       
3893       if(!strcmp(group_ou, kerberos_ou))
3894         sprintf(uid, "%s%s", contact_name, "_kerberos");
3895
3896       uid_v[0] = uid;
3897
3898       ADD_ATTR("sn", contact_v, LDAP_MOD_ADD);
3899       ADD_ATTR("uid", uid_v, LDAP_MOD_ADD);
3900     }
3901
3902   if(ActiveDirectory)
3903     {
3904       ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
3905     }
3906   else
3907     {
3908       ADD_ATTR("objectClass", objectClass_ldap_v, LDAP_MOD_ADD);
3909     }
3910
3911   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
3912   ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
3913   ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
3914
3915   if (Exchange)
3916     {
3917       if (!strcmp(group_ou, contact_ou) && email_isvalid(mail))
3918         {
3919           group_count = 0;
3920           group_base = NULL;
3921           
3922           sprintf(filter, "(&(objectClass=user)(cn=%s))", mail);
3923           attr_array[0] = "cn";
3924           attr_array[1] = NULL;
3925
3926           if ((rc = linklist_build(ld, bind_path, filter, attr_array,
3927                                    &group_base, &group_count, 
3928                                    LDAP_SCOPE_SUBTREE)) != 0) 
3929             {
3930               com_err(whoami, 0, "Unable to process contact %s : %s", 
3931                       user, ldap_err2string(rc));
3932               return(rc);
3933             }
3934       
3935           if (group_count) 
3936             {
3937               com_err(whoami, 0, "Object already exists with name %s",
3938                       user);
3939               return(1);
3940             }
3941
3942           linklist_free(group_base);
3943           group_base = NULL;
3944           group_count = 0;
3945       
3946           sprintf(filter, "(&(objectClass=group)(cn=%s))", mail);
3947           attr_array[0] = "cn";
3948           attr_array[1] = NULL;
3949
3950           if ((rc = linklist_build(ld, bind_path, filter, attr_array,
3951                                    &group_base, &group_count, 
3952                                    LDAP_SCOPE_SUBTREE)) != 0) 
3953             {
3954               com_err(whoami, 0, "Unable to process contact %s : %s", 
3955                       user, ldap_err2string(rc));
3956               return(rc);
3957             }
3958           
3959           if (group_count) 
3960             {
3961               com_err(whoami, 0, "Object already exists with name %s",
3962                       user);
3963               return(1);
3964             }
3965   
3966           linklist_free(group_base);
3967           group_count = 0;
3968           group_base = NULL;
3969           
3970           sprintf(filter, "(&(objectClass=user)(mail=%s))", mail);
3971           attr_array[0] = "cn";
3972           attr_array[1] = NULL;
3973
3974           if ((rc = linklist_build(ld, bind_path, filter, attr_array,
3975                                    &group_base, &group_count, 
3976                                    LDAP_SCOPE_SUBTREE)) != 0) 
3977             {
3978               com_err(whoami, 0, "Unable to process contact %s : %s", 
3979                       user, ldap_err2string(rc));
3980               return(rc);
3981             }
3982           
3983           if (group_count) 
3984             {
3985               com_err(whoami, 0, "Object already exists with name %s",
3986                       user);
3987               return(1);
3988             }
3989
3990           linklist_free(group_base);
3991           group_base = NULL;
3992           group_count = 0;
3993
3994           sprintf(filter, "(&(objectClass=group)(mail=%s))", mail);
3995           attr_array[0] = "cn";
3996           attr_array[1] = NULL;
3997
3998           if ((rc = linklist_build(ld, bind_path, filter, attr_array,
3999                                    &group_base, &group_count, 
4000                                    LDAP_SCOPE_SUBTREE)) != 0) 
4001             {
4002               com_err(whoami, 0, "Unable to process contact %s : %s", 
4003                       user, ldap_err2string(rc));
4004               return(rc);
4005             }
4006       
4007           if (group_count) 
4008             {
4009               com_err(whoami, 0, "Object already exists with name %s",
4010                       user);
4011               return(1);
4012             }
4013           
4014           linklist_free(group_base);
4015           group_base = NULL;
4016           group_count = 0;
4017           
4018           ADD_ATTR("mail", email_v, LDAP_MOD_ADD);
4019           ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_ADD);
4020           ADD_ATTR("proxyAddresses", proxy_address_external_v, LDAP_MOD_ADD);
4021           ADD_ATTR("targetAddress", target_address_v, LDAP_MOD_ADD);
4022           
4023           hide_address_lists_v[0] = "TRUE";
4024           ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
4025                    LDAP_MOD_ADD);
4026         }
4027     }
4028
4029   if(!ActiveDirectory) 
4030     {
4031       if((c = strchr(mail, '@')) == NULL)
4032           sprintf(temp, "%s@mit.edu", mail);
4033       else
4034           sprintf(temp, "%s", mail);
4035
4036       mail_routing_v[0] = temp;
4037       email_v[0] = temp;
4038       principal_v[0] = principal;
4039
4040       if(!strcmp(group_ou, contact_ou))
4041         {
4042           ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
4043           ADD_ATTR("eduPersonPrincipalName", mail_routing_v, LDAP_MOD_ADD);
4044         }
4045     }
4046
4047   mods[n] = NULL;
4048
4049   rc = ldap_add_ext_s(ld, new_dn, mods, NULL, NULL);
4050
4051   for (i = 0; i < n; i++)
4052     free(mods[i]);
4053   
4054   if (Exchange)
4055     {
4056       if ((rc != LDAP_SUCCESS) && (rc == LDAP_ALREADY_EXISTS) &&
4057           !strcmp(group_ou, contact_ou) && email_isvalid(mail))
4058         {
4059           n = 0;
4060           
4061           ADD_ATTR("mail", email_v, LDAP_MOD_REPLACE);
4062           ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_REPLACE);
4063           ADD_ATTR("proxyAddresses", proxy_address_external_v, 
4064                    LDAP_MOD_REPLACE);
4065           ADD_ATTR("targetAddress", target_address_v, LDAP_MOD_REPLACE);
4066
4067           hide_address_lists_v[0] = "TRUE";
4068           ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
4069                    LDAP_MOD_REPLACE);
4070     
4071           mods[n] = NULL;
4072           rc = ldap_modify_s(ld, new_dn, mods);
4073       
4074           if (rc) 
4075             {
4076               com_err(whoami, 0, "Unable to update contact %s", mail);
4077             }
4078       
4079           for (i = 0; i < n; i++)
4080             free(mods[i]);
4081         }
4082     }
4083
4084   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
4085     {
4086       com_err(whoami, 0, "Unable to create contact %s : %s",
4087               user, ldap_err2string(rc));
4088       return(rc);
4089     }
4090
4091   return(0);
4092 }
4093
4094 int user_update(LDAP *ldap_handle, char *dn_path, char *user_name,
4095                 char *Uid, char *MitId, char *MoiraId, int State,
4096                 char *WinHomeDir, char *WinProfileDir, char *first,
4097                 char *middle, char *last, char *shell, char *class)
4098 {
4099   LDAPMod   *mods[20];
4100   LK_ENTRY  *group_base;
4101   int  group_count;
4102   char distinguished_name[512];
4103   char displayName[256];
4104   char *mitMoiraId_v[] = {NULL, NULL};
4105   char *mitMoiraClass_v[] = {NULL, NULL};
4106   char *mitMoiraStatus_v[] = {NULL, NULL};
4107   char *uid_v[] = {NULL, NULL};
4108   char *mitid_v[] = {NULL, NULL};
4109   char *homedir_v[] = {NULL, NULL};
4110   char *winProfile_v[] = {NULL, NULL};
4111   char *drives_v[] = {NULL, NULL};
4112   char *userAccountControl_v[] = {NULL, NULL};
4113   char *alt_recipient_v[] = {NULL, NULL};
4114   char *hide_address_lists_v[] = {NULL, NULL};
4115   char *mail_v[] = {NULL, NULL};
4116   char *gid_v[] = {NULL, NULL};
4117   char *loginshell_v[] = {NULL, NULL};
4118   char *principal_v[] = {NULL, NULL};
4119   char userAccountControlStr[80];
4120   int  n;
4121   int  rc;
4122   int  i;
4123   int  OldUseSFU30;
4124   u_int userAccountControl = UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD | 
4125     UF_PASSWD_CANT_CHANGE;
4126   char filter[128];
4127   char *attr_array[3];
4128   char temp[1024];
4129   char mail[256];
4130   char contact_mail[256];
4131   char filter_exp[1024];
4132   char search_path[512];
4133   char TemplateDn[512];
4134   char TemplateSamName[128];
4135   char alt_recipient[256];
4136   char principal[256];
4137   char status[256];
4138   char acBERBuf[N_SD_BER_BYTES];
4139   LDAPControl sControl = {"1.2.840.113556.1.4.801",
4140                           { N_SD_BER_BYTES, acBERBuf },
4141                           TRUE};
4142   LDAPControl *apsServerControls[] = {&sControl, NULL};
4143   LDAPMessage *psMsg;
4144   LDAP_BERVAL   **ppsValues;
4145   ULONG dwInfo;
4146   char *argv[3];
4147   char *homeMDB;
4148   char *homeServerName;
4149   char *save_argv[7];
4150   char search_string[256];
4151   char *p, *q;
4152   char *mail_routing_v[] = {NULL, NULL};
4153   char *c;
4154
4155   dwInfo = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
4156     DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;
4157   BEREncodeSecurityBits(dwInfo, acBERBuf);
4158
4159   if (!check_string(user_name))
4160     {
4161       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", 
4162               user_name);
4163       return(AD_INVALID_NAME);
4164     }
4165   
4166   memset(contact_mail, '\0', sizeof(contact_mail));
4167   sprintf(contact_mail, "%s@mit.edu", user_name);
4168   memset(mail, '\0', sizeof(mail));
4169   sprintf(mail, "%s@%s", user_name, lowercase(ldap_domain));
4170   memset(alt_recipient, '\0', sizeof(alt_recipient));
4171   sprintf(alt_recipient, "cn=%s@mit.edu,%s,%s", user_name, contact_ou, 
4172           dn_path);
4173   sprintf(search_string, "@%s", uppercase(ldap_domain));
4174
4175   if (Exchange)
4176     {
4177       if(contact_create(ldap_handle, dn_path, contact_mail, contact_ou))
4178         {
4179           com_err(whoami, 0, "Unable to create user contact %s", contact_mail);
4180         }
4181     }
4182
4183   group_count = 0;
4184   group_base = NULL;
4185
4186   memset(displayName, '\0', sizeof(displayName));
4187
4188   if (strlen(MoiraId) != 0)
4189     {
4190       if(ActiveDirectory)
4191         {
4192           sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
4193         }
4194       else
4195         {
4196           sprintf(filter, 
4197                   "(&(objectClass=mitPerson)(mitMoiraId=%s))", MoiraId);
4198         }
4199
4200       attr_array[0] = "cn";
4201       attr_array[1] = NULL;
4202       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4203                                &group_base, &group_count, 
4204                                LDAP_SCOPE_SUBTREE)) != 0)
4205         {
4206           com_err(whoami, 0, "Unable to process user %s : %s",
4207                   user_name, ldap_err2string(rc));
4208           return(rc);
4209         }
4210     }
4211
4212   if (group_count != 1)
4213     {
4214       linklist_free(group_base);
4215       group_base = NULL;
4216       group_count = 0;
4217       sprintf(filter, "(sAMAccountName=%s)", user_name);
4218       attr_array[0] = "cn";
4219       attr_array[1] = NULL;
4220       sprintf(temp, "%s,%s", user_ou, dn_path);
4221       if ((rc = linklist_build(ldap_handle, temp, filter, attr_array, 
4222                                &group_base, &group_count, 
4223                                LDAP_SCOPE_SUBTREE)) != 0)
4224         {
4225           com_err(whoami, 0, "Unable to process user %s : %s",
4226                   user_name, ldap_err2string(rc));
4227           return(rc);
4228         }
4229     }
4230
4231   if (group_count != 1)
4232     {
4233       com_err(whoami, 0, "Unable to find user %s in directory",
4234               user_name);
4235       linklist_free(group_base);
4236       return(AD_NO_USER_FOUND);
4237     }
4238
4239   strcpy(distinguished_name, group_base->dn);
4240
4241   linklist_free(group_base);
4242   group_count = 0;
4243
4244   if(!ActiveDirectory) 
4245     {
4246       if (rc = moira_connect())
4247         {
4248           critical_alert("Ldap incremental", 
4249                          "Error contacting Moira server : %s",
4250                          error_message(rc));
4251           return;
4252         }
4253   
4254       argv[0] = user_name;
4255       
4256       if (!(rc = mr_query("get_pobox", 1, argv, save_query_info, save_argv)))
4257         {
4258           n = 0;
4259           ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_REPLACE);
4260           mods[n] = NULL;
4261           rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4262           
4263           if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
4264             rc = LDAP_SUCCESS;
4265
4266           if(rc)
4267             com_err(whoami, 0, 
4268                     "Unable to set the mailRoutingAddress for %s : %s",
4269                     user_name, ldap_err2string(rc));
4270           
4271           p = strdup(save_argv[3]);
4272           
4273           if((c = strchr(p, ',')) != NULL) 
4274             {
4275               q = strtok(p, ",");
4276               StringTrim(q);
4277
4278               if ((c = strchr(q, '@')) == NULL)
4279                 sprintf(temp, "%s@mit.edu", q);
4280               else
4281                 sprintf(temp, "%s", q);
4282               
4283               if(email_isvalid(temp) && State != US_DELETED) 
4284                 {
4285                   mail_routing_v[0]  = temp;
4286                   
4287                   n = 0;
4288                   ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
4289                   mods[n] = NULL;
4290                   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4291
4292                   if (rc == LDAP_ALREADY_EXISTS || 
4293                       rc == LDAP_TYPE_OR_VALUE_EXISTS)
4294                     rc = LDAP_SUCCESS;
4295     
4296                   if(rc)
4297                     com_err(whoami, 0, 
4298                             "Unable to set the mailRoutingAddress for %s : %s",
4299                             user_name, ldap_err2string(rc));
4300                 }
4301
4302               while((q = strtok(NULL, ",")) != NULL) {
4303                 StringTrim(q);
4304                 
4305                 if((c = strchr(q, '@')) == NULL) 
4306                   sprintf(temp, "%s@mit.edu", q);
4307                 else
4308                   sprintf(temp, "%s", q);
4309
4310                 if(email_isvalid(temp) && State != US_DELETED) 
4311                   {
4312                     mail_routing_v[0]  = temp;
4313                 
4314                     n = 0;
4315                     ADD_ATTR("mailRoutingAddress", mail_routing_v, 
4316                              LDAP_MOD_ADD);
4317                     mods[n] = NULL;
4318                     rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4319                     
4320                     if (rc == LDAP_ALREADY_EXISTS || 
4321                         rc == LDAP_TYPE_OR_VALUE_EXISTS)
4322                       rc = LDAP_SUCCESS;
4323                     
4324                     if(rc)
4325                       com_err(whoami, 0, 
4326                               "Unable to set the mailRoutingAddress for " 
4327                               "%s : %s",
4328                               user_name, ldap_err2string(rc));
4329                   }
4330               }
4331             } else {
4332               StringTrim(p);
4333
4334             if((c = strchr(p, '@')) == NULL)
4335               sprintf(temp, "%s@mit.edu", p);
4336             else
4337               sprintf(temp, "%s", p);
4338             
4339             if(email_isvalid(temp) && State != US_DELETED) 
4340               {
4341                 mail_routing_v[0]  = temp;
4342                 
4343                 n = 0;
4344                 ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
4345                 mods[n] = NULL;
4346                 rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4347                 
4348                 if (rc == LDAP_ALREADY_EXISTS || 
4349                     rc == LDAP_TYPE_OR_VALUE_EXISTS)
4350                   rc = LDAP_SUCCESS;
4351                 
4352                 if(rc)
4353                   com_err(whoami, 0, 
4354                           "Unable to set the mailRoutingAddress for %s : %s",
4355                           user_name, ldap_err2string(rc));
4356               }
4357             }
4358         }
4359       moira_disconnect();
4360     }
4361
4362   if ((strlen(MitId) != 0) && (MitId[0] == '9'))
4363     rc = attribute_update(ldap_handle, distinguished_name, MitId, 
4364                           "employeeID", user_name);
4365   else
4366     rc = attribute_update(ldap_handle, distinguished_name, "none", 
4367                           "employeeID", user_name);
4368
4369   if(strlen(first)) {
4370     strcat(displayName, first);
4371   }
4372
4373   if(strlen(middle)) {
4374     if(strlen(first)) 
4375       strcat(displayName, " ");
4376
4377     strcat(displayName, middle);
4378   }
4379
4380   if(strlen(last)) {
4381     if(strlen(middle) || strlen(first))
4382       strcat(displayName, " ");
4383
4384     strcat(displayName, last);
4385   }
4386
4387   if(strlen(displayName))
4388     rc = attribute_update(ldap_handle, distinguished_name, displayName, 
4389                           "displayName", user_name);
4390   else
4391     rc = attribute_update(ldap_handle, distinguished_name, user_name,
4392                           "displayName", user_name);
4393
4394   if(!ActiveDirectory)
4395     {
4396       if(strlen(displayName))
4397         rc = attribute_update(ldap_handle, distinguished_name, displayName, 
4398                               "cn", user_name);
4399       else
4400         rc = attribute_update(ldap_handle, distinguished_name, user_name,
4401                               "cn", user_name);
4402     }
4403
4404   if(!ActiveDirectory)
4405     {
4406       rc = attribute_update(ldap_handle, distinguished_name, displayName, 
4407                             "eduPersonNickname", user_name);
4408     }
4409
4410   if(strlen(first))
4411     rc = attribute_update(ldap_handle, distinguished_name, first, 
4412                           "givenName", user_name);
4413   else
4414     rc = attribute_update(ldap_handle, distinguished_name, "",
4415                           "givenName", user_name);
4416
4417   if(strlen(middle) == 1) 
4418     rc = attribute_update(ldap_handle, distinguished_name, middle,
4419                           "initials", user_name);
4420   else 
4421     rc = attribute_update(ldap_handle, distinguished_name, "",
4422                           "initials", user_name);
4423   
4424   if(strlen(last))
4425     rc = attribute_update(ldap_handle, distinguished_name, last,
4426                           "sn", user_name);
4427   else 
4428     rc = attribute_update(ldap_handle, distinguished_name, "",
4429                           "sn", user_name);
4430
4431   if(ActiveDirectory)
4432     {
4433       rc = attribute_update(ldap_handle, distinguished_name, Uid, "uid", 
4434                             user_name);
4435     }
4436   else
4437     {
4438       rc = attribute_update(ldap_handle, distinguished_name, user_name, "uid", 
4439                             user_name);
4440     }
4441     
4442   rc = attribute_update(ldap_handle, distinguished_name, MoiraId, 
4443                         "mitMoiraId", user_name);
4444
4445   n = 0;
4446   uid_v[0] = Uid;
4447
4448   if(ActiveDirectory)
4449     {
4450       if (!UseSFU30)
4451         {
4452           ADD_ATTR("uidNumber", uid_v, LDAP_MOD_REPLACE);
4453         }
4454       else
4455         {
4456           ADD_ATTR("msSFU30UidNumber", uid_v, LDAP_MOD_REPLACE);
4457         }
4458     }
4459   else
4460     {
4461       sprintf(principal, "%s@%s", user_name, PRIMARY_REALM);
4462       sprintf(status, "%d", State);
4463       principal_v[0] = principal;
4464       loginshell_v[0] = shell;
4465       mitMoiraClass_v[0] = class;
4466       mitMoiraStatus_v[0] = status;
4467       gid_v[0] = "101";
4468       ADD_ATTR("uidNumber", uid_v, LDAP_MOD_REPLACE);
4469       ADD_ATTR("gidNumber", gid_v, LDAP_MOD_REPLACE);
4470       ADD_ATTR("loginShell", loginshell_v, LDAP_MOD_REPLACE);
4471       ADD_ATTR("eduPersonPrincipalName", mail_v, LDAP_MOD_REPLACE);
4472       ADD_ATTR("mitMoiraClass", mitMoiraClass_v, LDAP_MOD_REPLACE);
4473       ADD_ATTR("mitMoiraStatus", mitMoiraStatus_v, LDAP_MOD_REPLACE);
4474     }
4475
4476   if ((State != US_NO_PASSWD) && (State != US_REGISTERED))
4477     {
4478       userAccountControl |= UF_ACCOUNTDISABLE;
4479
4480       if (Exchange)
4481         {
4482           hide_address_lists_v[0] = "TRUE";
4483           ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
4484                    LDAP_MOD_REPLACE);
4485         }
4486     }
4487   else
4488     {
4489       if (Exchange)
4490         {
4491           hide_address_lists_v[0] = NULL;
4492           ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
4493                    LDAP_MOD_REPLACE);
4494         }
4495     }
4496
4497   sprintf(userAccountControlStr, "%ld", userAccountControl);
4498   userAccountControl_v[0] = userAccountControlStr;
4499   ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_REPLACE);
4500
4501   if (Exchange)
4502     {
4503       if (rc = moira_connect())
4504         {
4505           critical_alert("Ldap incremental", 
4506                          "Error contacting Moira server : %s",
4507                          error_message(rc));
4508           return;
4509         }
4510  
4511       argv[0] = user_name;
4512
4513       if (!(rc = mr_query("get_pobox", 1, argv, save_query_info, save_argv)))
4514         {
4515           if(!strcmp(save_argv[1], "EXCHANGE") || 
4516              (strstr(save_argv[3], search_string) != NULL))
4517             {
4518               alt_recipient_v[0] = NULL;
4519               ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_REPLACE);
4520
4521               argv[0] = exchange_acl;
4522               argv[1] = "USER";
4523               argv[2] = user_name;
4524               
4525               rc = mr_query("add_member_to_list", 3, argv, NULL, NULL);
4526               
4527               if ((rc) && (rc != MR_EXISTS))
4528                 {
4529                   com_err(whoami, 0, "Unable to add user %s to %s: %s",
4530                           user_name, exchange_acl, error_message(rc));
4531                 }
4532             }
4533           else 
4534             {
4535               alt_recipient_v[0] = alt_recipient;
4536               ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_REPLACE);
4537               
4538               argv[0] = exchange_acl;
4539               argv[1] = "USER";
4540               argv[2] = user_name;
4541               
4542               rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL);
4543               
4544               if ((rc) && (rc != MR_NO_MATCH))
4545                 {  
4546                   com_err(whoami, 0,
4547                           "Unable to remove user %s from %s: %s, %d",
4548                           user_name, exchange_acl, error_message(rc), rc);
4549                 }  
4550             }
4551         }
4552       else
4553         {
4554           alt_recipient_v[0] = alt_recipient;
4555           ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_REPLACE);
4556           
4557           argv[0] = exchange_acl;
4558           argv[1] = "USER";
4559           argv[2] = user_name;
4560           
4561           rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL);
4562           
4563           if ((rc) && (rc != MR_NO_MATCH))
4564             {  
4565               com_err(whoami, 0,
4566                       "Unable to remove user %s from %s: %s, %d",
4567                       user_name, exchange_acl, error_message(rc), rc);
4568             }  
4569         }
4570       
4571       moira_disconnect();
4572     }
4573   else
4574     {
4575       mail_v[0] = contact_mail;
4576       ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
4577
4578       if(!ActiveDirectory)
4579         {
4580           ADD_ATTR("mitMoiraMail", mail_v, LDAP_MOD_REPLACE);
4581         }
4582     }
4583
4584   n = SetHomeDirectory(ldap_handle, user_name, distinguished_name, WinHomeDir, 
4585                        WinProfileDir, homedir_v, winProfile_v,
4586                        drives_v, mods, LDAP_MOD_REPLACE, n);
4587
4588   if(ActiveDirectory)
4589     {
4590       sprintf(filter_exp, "(sAMAccountName=%s)", "UserTemplate.u");
4591       sprintf(search_path, "%s,%s", security_template_ou, dn_path);
4592       attr_array[0] = "sAMAccountName";
4593       attr_array[1] = NULL;
4594       group_count = 0;
4595       group_base = NULL;
4596     
4597       if ((rc = linklist_build(ldap_handle, search_path, filter_exp, 
4598                                attr_array,
4599                                &group_base, &group_count, 
4600                                LDAP_SCOPE_SUBTREE) != 0))
4601         return(1);
4602       
4603       if (group_count != 1)
4604         {
4605           com_err(whoami, 0, "Unable to process user security template: %s - "
4606                   "security not set", "UserTemplate.u");
4607           return(1);
4608         }
4609
4610       strcpy(TemplateDn, group_base->dn);
4611       strcpy(TemplateSamName, group_base->value);
4612       linklist_free(group_base);
4613       group_base = NULL;
4614       group_count = 0;
4615       
4616       rc = ldap_search_ext_s(ldap_handle, search_path, LDAP_SCOPE_SUBTREE,
4617                              filter_exp, NULL, 0, apsServerControls, NULL,
4618                              NULL, 0, &psMsg);
4619
4620       if ((psMsg = ldap_first_entry(ldap_handle, psMsg)) == NULL)
4621         {
4622           com_err(whoami, 0, "Unable to find user security template: %s - "
4623                   "security not set", "UserTemplate.u");
4624           return(1);
4625         }
4626       
4627       ppsValues = ldap_get_values_len(ldap_handle, psMsg, 
4628                                       "ntSecurityDescriptor");
4629
4630       if (ppsValues == NULL)
4631         {
4632           com_err(whoami, 0, "Unable to find user security template: %s - "
4633                   "security not set", "UserTemplate.u");
4634           return(1);
4635         }
4636       
4637       ADD_ATTR("ntSecurityDescriptor", (char **)ppsValues,
4638                LDAP_MOD_REPLACE | LDAP_MOD_BVALUES);
4639     }
4640
4641   mods[n] = NULL;
4642
4643   if ((rc = ldap_modify_s(ldap_handle, distinguished_name, 
4644                           mods)) != LDAP_SUCCESS)
4645     {
4646       OldUseSFU30 = UseSFU30;
4647       SwitchSFU(mods, &UseSFU30, n);
4648       if (OldUseSFU30 != UseSFU30)
4649         rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4650       if (rc)
4651         {
4652           com_err(whoami, 0, "Unable to modify user data for %s : %s",
4653                   user_name, ldap_err2string(rc));
4654         }
4655     }
4656   
4657   for (i = 0; i < n; i++)
4658     free(mods[i]);
4659
4660   return(rc);
4661 }
4662
4663 int user_rename(LDAP *ldap_handle, char *dn_path, char *before_user_name, 
4664                 char *user_name)
4665 {
4666   LDAPMod *mods[20];
4667   char new_dn[256];
4668   char old_dn[256];
4669   char upn[256];
4670   char mail[256];
4671   char contact_mail[256];
4672   char proxy_address[256];
4673   char query_base_dn[256];
4674   char temp[256];
4675   char *userPrincipalName_v[] = {NULL, NULL};
4676   char *altSecurityIdentities_v[] = {NULL, NULL};
4677   char *name_v[] = {NULL, NULL};
4678   char *samAccountName_v[] = {NULL, NULL};
4679   char *mail_v[] = {NULL, NULL};
4680   char *mail_nickname_v[] = {NULL, NULL};
4681   char *proxy_address_v[] = {NULL, NULL};
4682   char *query_base_dn_v[] = {NULL, NULL};
4683   char *principal_v[] = {NULL, NULL};
4684   char principal[256];
4685   int  n;
4686   int  rc;
4687   int  i;
4688
4689   if (!check_string(before_user_name))
4690     {
4691       com_err(whoami, 0, 
4692               "Unable to process invalid LDAP user name %s", before_user_name);
4693       return(AD_INVALID_NAME);
4694     }
4695
4696   if (!check_string(user_name))
4697     {
4698       com_err(whoami, 0, 
4699               "Unable to process invalid LDAP user name %s", user_name);
4700       return(AD_INVALID_NAME);
4701     }
4702
4703   strcpy(user_name, user_name);
4704  
4705   if(ActiveDirectory)
4706     sprintf(old_dn, "cn=%s,%s,%s", before_user_name, user_ou, dn_path);
4707   else
4708     sprintf(old_dn, "uid=%s,%s,%s", before_user_name, user_ou, dn_path);
4709
4710   if(ActiveDirectory)
4711     sprintf(new_dn, "cn=%s", user_name);
4712   else
4713     sprintf(new_dn, "uid=%s", user_name);
4714
4715   sprintf(mail, "%s@%s", user_name, lowercase(ldap_domain));
4716   sprintf(contact_mail, "%s@mit.edu", user_name);
4717   sprintf(proxy_address, "SMTP:%s@%s", user_name, lowercase(ldap_domain)); 
4718   sprintf(principal, "%s@%s", user_name, PRIMARY_REALM);
4719
4720   if ((rc = ldap_rename_s(ldap_handle, old_dn, new_dn, NULL, TRUE, 
4721                            NULL, NULL)) != LDAP_SUCCESS)
4722     {
4723       com_err(whoami, 0, "Unable to rename user from %s to %s : %s",
4724               before_user_name, user_name, ldap_err2string(rc));
4725       return(rc);
4726     }
4727
4728   if (Exchange)
4729     {
4730       sprintf(temp, "cn=%s@mit.edu,%s,%s", before_user_name, contact_ou, 
4731               dn_path);
4732
4733       if(rc = ldap_delete_s(ldap_handle, temp))
4734         {
4735           com_err(whoami, 0, "Unable to delete user contact for %s",
4736                   user_name);
4737         }
4738       
4739       if(contact_create(ldap_handle, dn_path, contact_mail, contact_ou))
4740         {
4741           com_err(whoami, 0, "Unable to create user contact %s", contact_mail);
4742         }
4743     }
4744
4745   name_v[0] = user_name;
4746   sprintf(upn, "%s@%s", user_name, ldap_domain);
4747   userPrincipalName_v[0] = upn;
4748   principal_v[0] = principal;
4749   sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
4750   sprintf(query_base_dn, "%s%s", ADDRESS_LIST_PREFIX, dn_path);
4751   altSecurityIdentities_v[0] = temp;
4752   samAccountName_v[0] = user_name;
4753   mail_v[0] = mail;
4754   mail_nickname_v[0] = user_name;
4755   proxy_address_v[0] = proxy_address; 
4756   query_base_dn_v[0] = query_base_dn;
4757
4758   n = 0;
4759   ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_REPLACE);
4760   ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_REPLACE);
4761   ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
4762   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_REPLACE);
4763
4764   if(!ActiveDirectory)
4765     {
4766       ADD_ATTR("uid", samAccountName_v, LDAP_MOD_REPLACE);
4767       ADD_ATTR("eduPersonPrincipalName", mail_v, LDAP_MOD_REPLACE);
4768       ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
4769       ADD_ATTR("eduPersonNickname", name_v, LDAP_MOD_REPLACE);
4770       ADD_ATTR("name", name_v, LDAP_MOD_REPLACE);
4771     }
4772
4773   if (Exchange)
4774     {
4775       ADD_ATTR("msExchQueryBaseDN", query_base_dn_v, LDAP_MOD_REPLACE);
4776       ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_REPLACE); 
4777       ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE); 
4778       ADD_ATTR("proxyAddresses", proxy_address_v, LDAP_MOD_REPLACE);
4779     }
4780   else
4781     {
4782       mail_v[0] = contact_mail;
4783       ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE); 
4784
4785       if(!ActiveDirectory)
4786         {
4787           ADD_ATTR("mitMoiraMail", mail_v, LDAP_MOD_REPLACE);
4788         }
4789     }
4790
4791   mods[n] = NULL;
4792   
4793   if(ActiveDirectory)
4794     sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, dn_path);
4795   else
4796     sprintf(new_dn, "uid=%s,%s,%s", user_name, user_ou, dn_path);
4797
4798   if ((rc = ldap_modify_s(ldap_handle, new_dn, mods)) != LDAP_SUCCESS)
4799     {
4800       com_err(whoami, 0, 
4801               "Unable to modify user data for %s after renaming : %s",
4802               user_name, ldap_err2string(rc));
4803     }
4804   
4805   for (i = 0; i < n; i++)
4806     free(mods[i]);
4807
4808   return(rc);
4809 }
4810
4811 int user_create(int ac, char **av, void *ptr)
4812 {
4813   LDAPMod *mods[20];
4814   char new_dn[256];
4815   char user_name[256];
4816   char sam_name[256];
4817   char upn[256];
4818   char mail[256];
4819   char contact_mail[256];
4820   char proxy_address[256];
4821   char mail_nickname[256];
4822   char query_base_dn[256];
4823   char displayName[256];
4824   char address_book[256];
4825   char alt_recipient[256];
4826   char *cn_v[] = {NULL, NULL};
4827   char *objectClass_v[] = {"top", "person", "organizationalPerson",
4828                            "user", NULL};
4829   char *objectClass_ldap_v[] = {"top", 
4830                                 "eduPerson", "posixAccount", 
4831                                 "apple-user", "shadowAccount",
4832                                 "microsoftComTop", "securityPrincipal",
4833                                 "inetOrgPerson", "user", 
4834                                 "organizationalPerson", "person",
4835                                 "mailRecipient", NULL};
4836
4837   char *samAccountName_v[] = {NULL, NULL};
4838   char *altSecurityIdentities_v[] = {NULL, NULL};
4839   char *mitMoiraId_v[] = {NULL, NULL};
4840   char *mitMoiraClass_v[] = {NULL, NULL};
4841   char *mitMoiraStatus_v[] = {NULL, NULL};
4842   char *name_v[] = {NULL, NULL};
4843   char *desc_v[] = {NULL, NULL};
4844   char *userPrincipalName_v[] = {NULL, NULL};
4845   char *userAccountControl_v[] = {NULL, NULL};
4846   char *uid_v[] = {NULL, NULL};
4847   char *gid_v[] = {NULL, NULL};
4848   char *mitid_v[] = {NULL, NULL};
4849   char *homedir_v[] = {NULL, NULL};
4850   char *winProfile_v[] = {NULL, NULL};
4851   char *drives_v[] = {NULL, NULL};
4852   char *mail_v[] = {NULL, NULL};
4853   char *givenName_v[] = {NULL, NULL};
4854   char *sn_v[] = {NULL, NULL};
4855   char *initials_v[] = {NULL, NULL};
4856   char *displayName_v[] = {NULL, NULL};
4857   char *proxy_address_v[] = {NULL, NULL};
4858   char *mail_nickname_v[] = {NULL, NULL};
4859   char *query_base_dn_v[] = {NULL, NULL};
4860   char *address_book_v[] = {NULL, NULL};
4861   char *homeMDB_v[] = {NULL, NULL};
4862   char *homeServerName_v[] = {NULL, NULL};
4863   char *mdbUseDefaults_v[] = {NULL, NULL};
4864   char *mailbox_guid_v[] = {NULL, NULL};
4865   char *user_culture_v[] = {NULL, NULL};
4866   char *user_account_control_v[] = {NULL, NULL};
4867   char *msexch_version_v[] = {NULL, NULL};
4868   char *alt_recipient_v[] = {NULL, NULL};
4869   char *hide_address_lists_v[] = {NULL, NULL};
4870   char *principal_v[] = {NULL, NULL};
4871   char *loginshell_v[] = {NULL, NULL};
4872   char userAccountControlStr[80];
4873   char temp[1024];
4874   char principal[256];
4875   char filter_exp[1024];
4876   char search_path[512];
4877   char *attr_array[3];
4878   u_int userAccountControl = UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD | 
4879     UF_PASSWD_CANT_CHANGE; 
4880   int  n;
4881   int  rc;
4882   int  i;
4883   int  OldUseSFU30;
4884   char **call_args;
4885   char WinHomeDir[1024];
4886   char WinProfileDir[1024];
4887   char *homeMDB;
4888   char *homeServerName;
4889   ULONG dwInfo;
4890   char acBERBuf[N_SD_BER_BYTES];
4891   LK_ENTRY  *group_base;
4892   int    group_count;
4893   char TemplateDn[512];
4894   char TemplateSamName[128];
4895   LDAP_BERVAL **ppsValues;
4896   LDAPControl sControl = {"1.2.840.113556.1.4.801",
4897                           { N_SD_BER_BYTES, acBERBuf },
4898                           TRUE};
4899   LDAPControl *apsServerControls[] = {&sControl, NULL};
4900   LDAPMessage *psMsg;
4901   char *argv[3];
4902   char *save_argv[7];
4903   char search_string[256];
4904   char *o_v[] = {NULL, NULL};
4905   char *p, *q;
4906   char *mail_routing_v[] = {NULL, NULL};
4907   char *c;
4908
4909   call_args = ptr;
4910
4911   dwInfo = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
4912     DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;
4913   BEREncodeSecurityBits(dwInfo, acBERBuf);
4914
4915   if (!check_string(av[U_NAME]))
4916     {
4917       callback_rc = AD_INVALID_NAME;
4918       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", 
4919               av[U_NAME]);
4920       return(AD_INVALID_NAME);
4921     }
4922
4923   memset(WinHomeDir, '\0', sizeof(WinHomeDir));
4924   memset(WinProfileDir, '\0', sizeof(WinProfileDir));
4925   memset(displayName, '\0', sizeof(displayName));
4926   memset(query_base_dn, '\0', sizeof(query_base_dn));
4927   strcpy(WinHomeDir, av[U_WINHOMEDIR]);
4928   strcpy(WinProfileDir, av[U_WINPROFILEDIR]);
4929   strcpy(user_name, av[U_NAME]);
4930   sprintf(upn, "%s@%s", user_name, ldap_domain);
4931   sprintf(sam_name, "%s", av[U_NAME]);
4932
4933   if(strlen(av[U_FIRST])) {
4934     strcat(displayName, av[U_FIRST]);
4935   }
4936
4937   if(strlen(av[U_MIDDLE])) {
4938     if(strlen(av[U_FIRST]))
4939        strcat(displayName, " "); 
4940   
4941     strcat(displayName, av[U_MIDDLE]);
4942   }
4943
4944   if(strlen(av[U_LAST])) {
4945     if(strlen(av[U_FIRST]) || strlen(av[U_MIDDLE]))
4946       strcat(displayName, " ");
4947
4948     strcat(displayName, av[U_LAST]);
4949   }
4950
4951   samAccountName_v[0] = sam_name;
4952   if ((atoi(av[U_STATE]) != US_NO_PASSWD) && 
4953       (atoi(av[U_STATE]) != US_REGISTERED))
4954     {
4955       userAccountControl |= UF_ACCOUNTDISABLE;
4956
4957       if (Exchange)
4958         {
4959           hide_address_lists_v[0] = "TRUE";
4960           ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
4961                    LDAP_MOD_ADD);
4962         }
4963     }
4964
4965   sprintf(userAccountControlStr, "%ld", userAccountControl);
4966   userAccountControl_v[0] = userAccountControlStr;
4967   userPrincipalName_v[0] = upn;
4968   
4969   if(ActiveDirectory)
4970     cn_v[0] = user_name;
4971   else
4972     cn_v[0] = displayName;
4973     
4974   name_v[0] = user_name;
4975   desc_v[0] = "Auto account created by Moira";
4976   mail_v[0] = mail;
4977   givenName_v[0] = av[U_FIRST];
4978
4979   if(ActiveDirectory)
4980     sn_v[0] = av[U_LAST];
4981   else
4982     if(strlen(av[U_LAST]))
4983       sn_v[0] = av[U_LAST];
4984     else
4985       sn_v[0] = av[U_NAME];
4986
4987   displayName_v[0] = displayName;
4988   mail_nickname_v[0] = user_name;
4989   o_v[0] = "Massachusetts Institute of Technology";
4990
4991   sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
4992   sprintf(principal, "%s@%s", user_name, PRIMARY_REALM);
4993   altSecurityIdentities_v[0] = temp;    
4994   principal_v[0] = principal;
4995
4996   if(ActiveDirectory)
4997     sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, call_args[1]);
4998   else
4999     sprintf(new_dn, "uid=%s,%s,%s", user_name, user_ou, call_args[1]);
5000
5001   sprintf(mail,"%s@%s", user_name, lowercase(ldap_domain));
5002   sprintf(contact_mail, "%s@mit.edu", user_name);
5003   sprintf(query_base_dn, "%s%s", ADDRESS_LIST_PREFIX, call_args[1]);
5004   query_base_dn_v[0] = query_base_dn;
5005   sprintf(alt_recipient, "cn=%s@mit.edu,%s,%s", user_name, contact_ou, 
5006           call_args[1]);
5007   sprintf(search_string, "@%s", uppercase(ldap_domain));
5008
5009   if (Exchange)
5010     {
5011       if(contact_create((LDAP *)call_args[0], call_args[1], contact_mail, 
5012                         contact_ou))
5013         {
5014           com_err(whoami, 0, "Unable to create user contact %s", 
5015                   contact_mail);
5016         }
5017       
5018       if(find_homeMDB((LDAP *)call_args[0], call_args[1], &homeMDB, 
5019                       &homeServerName)) 
5020         {
5021           com_err(whoami, 0, "Unable to locate homeMB and homeServerName");
5022           return(1);
5023         }
5024       
5025       com_err(whoami, 0, "homeMDB:%s", homeMDB);
5026       com_err(whoami, 0, "homeServerName:%s", homeServerName);
5027   
5028       homeMDB_v[0] = homeMDB;
5029       homeServerName_v[0] = homeServerName; 
5030     }
5031
5032   n = 0;
5033
5034   ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
5035   
5036   if(ActiveDirectory) 
5037     {
5038       ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
5039     }
5040   else
5041     {
5042       ADD_ATTR("objectClass", objectClass_ldap_v, LDAP_MOD_ADD);
5043     }
5044
5045   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
5046   ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_ADD);
5047   ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_ADD);
5048   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
5049   ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
5050
5051   if (Exchange)
5052     {
5053       ADD_ATTR("msExchQueryBaseDN", query_base_dn_v, LDAP_MOD_ADD);
5054       ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_ADD);
5055       ADD_ATTR("homeMDB", homeMDB_v, LDAP_MOD_ADD);
5056       mdbUseDefaults_v[0] = "TRUE";
5057       ADD_ATTR("mdbUseDefaults", mdbUseDefaults_v, LDAP_MOD_ADD);
5058       ADD_ATTR("msExchHomeServerName", homeServerName_v, LDAP_MOD_ADD); 
5059       
5060       argv[0] = user_name;
5061     
5062       if (!(rc = mr_query("get_pobox", 1, argv, save_query_info, save_argv)))
5063         {
5064           if(!strcmp(save_argv[1], "EXCHANGE") || 
5065              (strstr(save_argv[3], search_string) != NULL))
5066             {
5067               argv[0] = exchange_acl;
5068               argv[1] = "USER";
5069               argv[2] = user_name;
5070               
5071               rc = mr_query("add_member_to_list", 3, argv, NULL, NULL);
5072               
5073               if ((rc) && (rc != MR_EXISTS))
5074                 {
5075                   com_err(whoami, 0, "Unable to add user %s to %s: %s",
5076                           user_name, exchange_acl, error_message(rc));
5077                 }
5078             } 
5079           else 
5080             {
5081               alt_recipient_v[0] = alt_recipient;
5082               ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_ADD);
5083             }
5084         }
5085       else
5086         {
5087           alt_recipient_v[0] = alt_recipient;
5088           ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_ADD);
5089           
5090           com_err(whoami, 0, "Unable to fetch pobox for %s", user_name);
5091         }
5092     }
5093   else
5094     {
5095       mail_v[0] = contact_mail;
5096       ADD_ATTR("mail", mail_v, LDAP_MOD_ADD);
5097
5098       if(!ActiveDirectory)
5099         {
5100           ADD_ATTR("mitMoiraMail", mail_v, LDAP_MOD_ADD);
5101         }
5102     }
5103
5104   if(strlen(av[U_FIRST])) {
5105     ADD_ATTR("givenName", givenName_v, LDAP_MOD_ADD);
5106   }
5107
5108   if(strlen(av[U_LAST]) || strlen(av[U_NAME])) {
5109     ADD_ATTR("sn", sn_v, LDAP_MOD_ADD);
5110   }
5111
5112   if(strlen(av[U_FIRST]) || strlen(av[U_MIDDLE]) || strlen(av[U_LAST])) {
5113     ADD_ATTR("displayName", displayName_v, LDAP_MOD_ADD);
5114
5115     if(!ActiveDirectory)
5116       {
5117         ADD_ATTR("eduPersonNickname", displayName_v, LDAP_MOD_ADD);      
5118       }
5119   } else {
5120     ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
5121
5122     if(!ActiveDirectory)
5123       {
5124         ADD_ATTR("eduPersonNickname", name_v, LDAP_MOD_ADD);            
5125       }
5126   }
5127
5128   if (strlen(av[U_MIDDLE]) == 1) {
5129     initials_v[0] = av[U_MIDDLE];
5130     ADD_ATTR("initials", initials_v, LDAP_MOD_ADD);
5131   }
5132
5133   if (strlen(call_args[2]) != 0)    
5134     {
5135       mitMoiraId_v[0] = call_args[2];
5136       ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_ADD); 
5137     }
5138
5139   ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_ADD);
5140
5141   if(!ActiveDirectory)
5142     {
5143       loginshell_v[0] = av[U_SHELL];
5144       mitMoiraClass_v[0] = av[U_CLASS];
5145       mitMoiraStatus_v[0] = av[U_STATE];
5146       ADD_ATTR("loginShell", loginshell_v, LDAP_MOD_ADD);
5147       ADD_ATTR("uid", samAccountName_v, LDAP_MOD_ADD);
5148       ADD_ATTR("eduPersonPrincipalName", mail_v, LDAP_MOD_ADD);
5149       ADD_ATTR("o", o_v, LDAP_MOD_ADD);
5150       ADD_ATTR("mitMoiraClass", mitMoiraClass_v, LDAP_MOD_ADD);
5151       ADD_ATTR("mitMoiraStatus", mitMoiraStatus_v, LDAP_MOD_ADD);
5152     }
5153
5154   if (strlen(av[U_UID]) != 0)
5155     {
5156       uid_v[0] = av[U_UID];
5157
5158       if(ActiveDirectory) 
5159         {
5160           ADD_ATTR("uid", uid_v, LDAP_MOD_ADD);
5161         }
5162       else
5163         {
5164           gid_v[0] = "101";
5165           ADD_ATTR("uidNumber", uid_v, LDAP_MOD_ADD);
5166           ADD_ATTR("gidNumber", gid_v, LDAP_MOD_ADD);
5167         }
5168
5169       if(ActiveDirectory)
5170         {
5171           if (!UseSFU30)
5172             {
5173               ADD_ATTR("uidNumber", uid_v, LDAP_MOD_ADD);
5174             }
5175           else
5176             {
5177               ADD_ATTR("msSFU30UidNumber", uid_v, LDAP_MOD_ADD);
5178             }
5179         }
5180     }
5181
5182   if ((strlen(av[U_MITID]) != 0) && (av[U_MITID][0] == '9'))
5183       mitid_v[0] = av[U_MITID];
5184   else
5185       mitid_v[0] = "none";
5186
5187   ADD_ATTR("employeeID", mitid_v, LDAP_MOD_ADD);
5188
5189   n = SetHomeDirectory((LDAP *)call_args[0], user_name, new_dn, 
5190                        WinHomeDir, WinProfileDir, homedir_v, winProfile_v,
5191                        drives_v, mods, LDAP_MOD_ADD, n);
5192   
5193   if(ActiveDirectory) 
5194     {
5195       sprintf(filter_exp, "(sAMAccountName=%s)", "UserTemplate.u");
5196       sprintf(search_path, "%s,%s", security_template_ou, call_args[1]);
5197       attr_array[0] = "sAMAccountName";
5198       attr_array[1] = NULL;
5199       group_count = 0;
5200       group_base = NULL;
5201       
5202       if ((rc = linklist_build((LDAP *)call_args[0], search_path, filter_exp, 
5203                                attr_array, &group_base, &group_count, 
5204                                LDAP_SCOPE_SUBTREE) != 0))
5205         return(1);
5206       
5207       if (group_count != 1)
5208         {
5209           com_err(whoami, 0, "Unable to process user security template: %s - "
5210                   "security not set", "UserTemplate.u");
5211           return(1);
5212         }
5213       
5214       strcpy(TemplateDn, group_base->dn);
5215       strcpy(TemplateSamName, group_base->value);
5216       linklist_free(group_base);
5217       group_base = NULL;
5218       group_count = 0;
5219       
5220       rc = ldap_search_ext_s((LDAP *)call_args[0], search_path, 
5221                              LDAP_SCOPE_SUBTREE, filter_exp, NULL, 0, 
5222                              apsServerControls, NULL,
5223                              NULL, 0, &psMsg);
5224       
5225       if ((psMsg = ldap_first_entry((LDAP *)call_args[0], psMsg)) == NULL)
5226         {
5227           com_err(whoami, 0, "Unable to find user security template: %s - "
5228                   "security not set", "UserTemplate.u");
5229           return(1);
5230         }
5231       
5232       ppsValues = ldap_get_values_len((LDAP *)call_args[0], psMsg, 
5233                                       "ntSecurityDescriptor");
5234       if (ppsValues == NULL)
5235         {
5236           com_err(whoami, 0, "Unable to find user security template: %s - "
5237                   "security not set", "UserTemplate.u");
5238           return(1);
5239         }
5240       
5241       ADD_ATTR("ntSecurityDescriptor", (char **)ppsValues,
5242                LDAP_MOD_REPLACE | LDAP_MOD_BVALUES); 
5243     }
5244
5245   mods[n] = NULL;
5246
5247   rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
5248
5249   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
5250     {
5251       OldUseSFU30 = UseSFU30;
5252       SwitchSFU(mods, &UseSFU30, n);
5253       if (OldUseSFU30 != UseSFU30)
5254         rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
5255     }
5256
5257   for (i = 0; i < n; i++)
5258     free(mods[i]);
5259
5260   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
5261     {
5262       com_err(whoami, 0, "Unable to create user %s : %s",
5263               user_name, ldap_err2string(rc));
5264       callback_rc = rc;
5265       return(rc);
5266     }
5267
5268   if ((rc == LDAP_SUCCESS) && (SetPassword))
5269     {
5270       if ((rc = set_password(sam_name, "", ldap_domain)) != 0)
5271         {
5272           ad_kdc_disconnect();
5273           if (!ad_server_connect(default_server, ldap_domain))
5274             {
5275               com_err(whoami, 0, "Unable to set password for user %s : %s",
5276                       user_name, 
5277                       "cannot get changepw ticket from windows domain");
5278             }
5279           else
5280             {
5281               if ((rc = set_password(sam_name, "", ldap_domain)) != 0)
5282                 {
5283                   com_err(whoami, 0, "Unable to set password for user %s "
5284                           ": %ld", user_name, rc);
5285                 }
5286             }
5287         }
5288     }
5289
5290   if(!ActiveDirectory) 
5291     {
5292       if (rc = moira_connect())
5293         {
5294           critical_alert("Ldap incremental", 
5295                          "Error contacting Moira server : %s",
5296                          error_message(rc));
5297           return;
5298         }
5299   
5300       argv[0] = user_name;
5301       
5302       if (!(rc = mr_query("get_pobox", 1, argv, save_query_info, save_argv)))
5303         {
5304           n = 0;
5305           ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_REPLACE);
5306           mods[n] = NULL;
5307           rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5308            
5309           if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
5310             rc = LDAP_SUCCESS;
5311
5312           if(rc)
5313             com_err(whoami, 0,
5314                     "Unable to set the mailRoutingAddress for %s : %s",
5315                     user_name, ldap_err2string(rc));
5316
5317           p = strdup(save_argv[3]);
5318           
5319           if((c = strchr(p, ',')) != NULL) {
5320             q = strtok(p, ",");
5321             StringTrim(q);
5322
5323             if ((c = strchr(q, '@')) == NULL)
5324               sprintf(temp, "%s@mit.edu", q);
5325             else
5326               sprintf(temp, "%s", q);
5327
5328             if(email_isvalid(temp) && atoi(av[U_STATE]) != US_DELETED) 
5329               {
5330                 mail_routing_v[0]  = temp;
5331
5332                 n = 0;
5333                 ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
5334                 mods[n] = NULL;
5335                 rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5336                 
5337                 if (rc == LDAP_ALREADY_EXISTS || 
5338                     rc == LDAP_TYPE_OR_VALUE_EXISTS)
5339                   rc = LDAP_SUCCESS;
5340                 
5341                 if(rc)
5342                   com_err(whoami, 0, 
5343                           "Unable to set the mailRoutingAddress for %s : %s",
5344                           user_name, ldap_err2string(rc));
5345               }
5346
5347             while((q = strtok(NULL, ",")) != NULL) {
5348               StringTrim(q);
5349
5350               if((c = strchr(q, '@')) == NULL)
5351                 sprintf(temp, "%s@mit.edu", q);
5352               else
5353                 sprintf(temp, "%s", q);
5354
5355               if(email_isvalid(temp) && atoi(av[U_STATE]) != US_DELETED)
5356                 {
5357                   mail_routing_v[0]  = temp;
5358                   
5359                   n = 0;
5360                   ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
5361                   mods[n] = NULL;
5362                   rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5363                   
5364                   if (rc == LDAP_ALREADY_EXISTS || 
5365                       rc == LDAP_TYPE_OR_VALUE_EXISTS)
5366                     rc = LDAP_SUCCESS;
5367                   
5368                   if(rc)
5369                     com_err(whoami, 0, 
5370                             "Unable to set the mailRoutingAddress for %s : %s",
5371                             user_name, ldap_err2string(rc));
5372                 }
5373             }
5374           } else {
5375             StringTrim(p);
5376
5377             if((c = strchr(p, '@')) == NULL)
5378               sprintf(temp, "%s@mit.edu", p);
5379             else
5380               sprintf(temp, "%s", p);
5381
5382             if(email_isvalid(temp) && atoi(av[U_STATE]) != US_DELETED) 
5383               {
5384                 mail_routing_v[0]  = temp;
5385                 
5386                 n = 0;
5387                 ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
5388                 mods[n] = NULL;
5389                 rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5390                 
5391                 if (rc == LDAP_ALREADY_EXISTS || 
5392                     rc == LDAP_TYPE_OR_VALUE_EXISTS)
5393                   rc = LDAP_SUCCESS;
5394                 
5395                 if(rc)
5396                   com_err(whoami, 0, 
5397                           "Unable to set the mailRoutingAddress for %s : %s",
5398                           user_name, ldap_err2string(rc));
5399               }
5400           }
5401         }
5402       moira_disconnect();
5403     }
5404
5405   return(0);
5406 }
5407
5408 int user_change_status(LDAP *ldap_handle, char *dn_path, 
5409                        char *user_name, char *MoiraId,
5410                        int operation)
5411 {
5412   char      filter[128];
5413   char      *attr_array[3];
5414   char      temp[256];
5415   char      distinguished_name[1024];
5416   char      **modvalues;
5417   char      *mitMoiraId_v[] = {NULL, NULL};
5418   LDAPMod   *mods[20];
5419   LK_ENTRY  *group_base;
5420   int       group_count;
5421   int       rc;
5422   int       i;
5423   int       n;
5424   ULONG     ulongValue;
5425
5426   if (!check_string(user_name))
5427     {
5428       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", 
5429               user_name);
5430       return(AD_INVALID_NAME);
5431     }
5432
5433   group_count = 0;
5434   group_base = NULL;
5435
5436   if (strlen(MoiraId) != 0)
5437     {
5438       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
5439       attr_array[0] = "UserAccountControl";
5440       attr_array[1] = NULL;
5441       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
5442                                &group_base, &group_count, 
5443                                LDAP_SCOPE_SUBTREE)) != 0)
5444         {
5445           com_err(whoami, 0, "Unable to process user %s : %s",
5446                   user_name, ldap_err2string(rc));
5447           return(rc);
5448         }
5449     }
5450
5451   if (group_count != 1)
5452     {
5453       linklist_free(group_base);
5454       group_count = 0;
5455       group_base = NULL;
5456       sprintf(filter, "(sAMAccountName=%s)", user_name);
5457       attr_array[0] = "UserAccountControl";
5458       attr_array[1] = NULL;
5459       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
5460                                &group_base, &group_count, 
5461                                LDAP_SCOPE_SUBTREE)) != 0)
5462         {
5463           com_err(whoami, 0, "Unable to process user %s : %s",
5464                   user_name, ldap_err2string(rc));
5465           return(rc);
5466         }
5467     }
5468   
5469   if (group_count != 1)
5470     {
5471       linklist_free(group_base);
5472       com_err(whoami, 0, "Unable to find user %s in directory",
5473               user_name);
5474       return(LDAP_NO_SUCH_OBJECT);
5475     }
5476
5477   strcpy(distinguished_name, group_base->dn);
5478   ulongValue = atoi((*group_base).value);
5479
5480   if (operation == MEMBER_DEACTIVATE)
5481     ulongValue |= UF_ACCOUNTDISABLE;
5482   else    
5483     ulongValue &= ~UF_ACCOUNTDISABLE;
5484
5485   sprintf(temp, "%ld", ulongValue);
5486
5487   if ((rc = construct_newvalues(group_base, group_count, (*group_base).value, 
5488                                 temp, &modvalues, REPLACE)) == 1)
5489     goto cleanup;
5490
5491   linklist_free(group_base);
5492   group_base = NULL;
5493   group_count = 0;
5494   n = 0;
5495   ADD_ATTR("UserAccountControl", modvalues, LDAP_MOD_REPLACE);
5496
5497   if (strlen(MoiraId) != 0)
5498     {
5499     mitMoiraId_v[0] = MoiraId;
5500     ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
5501     }
5502
5503   mods[n] = NULL;
5504   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
5505
5506   for (i = 0; i < n; i++)
5507     free(mods[i]);
5508
5509   free_values(modvalues);
5510
5511   if (rc != LDAP_SUCCESS)
5512     {
5513       com_err(whoami, 0, "Unable to change status of user %s : %s",
5514               user_name, ldap_err2string(rc));
5515     }
5516   
5517  cleanup:
5518   return(rc);
5519 }
5520
5521 int user_delete(LDAP *ldap_handle, char *dn_path, 
5522                 char *u_name, char *MoiraId)
5523 {
5524   char      filter[128];
5525   char      *attr_array[3];
5526   char      distinguished_name[1024];
5527   char      user_name[512];
5528   LK_ENTRY  *group_base;
5529   int       group_count;
5530   int       rc;
5531   char      temp[256];
5532
5533   if (!check_string(u_name))
5534     return(AD_INVALID_NAME);
5535
5536   strcpy(user_name, u_name);
5537   group_count = 0;
5538   group_base = NULL;
5539
5540   if (strlen(MoiraId) != 0)
5541     {
5542       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
5543       attr_array[0] = "name";
5544       attr_array[1] = NULL;
5545       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
5546                                &group_base, &group_count, 
5547                                LDAP_SCOPE_SUBTREE)) != 0)
5548         {
5549           com_err(whoami, 0, "Unable to process user %s : %s",
5550                   user_name, ldap_err2string(rc));
5551           goto cleanup;
5552         }
5553     }
5554   
5555   if (group_count != 1)
5556     {
5557       linklist_free(group_base);
5558       group_count = 0;
5559       group_base = NULL;
5560       sprintf(filter, "(sAMAccountName=%s)", user_name);
5561       attr_array[0] = "name";
5562       attr_array[1] = NULL;
5563       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
5564                                &group_base, &group_count, 
5565                                LDAP_SCOPE_SUBTREE)) != 0)
5566         {
5567           com_err(whoami, 0, "Unable to process user %s : %s",
5568                   user_name, ldap_err2string(rc));
5569           goto cleanup;
5570         }
5571     }
5572
5573   if (group_count != 1)
5574     {
5575       goto cleanup;
5576     }
5577   
5578   strcpy(distinguished_name, group_base->dn);
5579
5580   if (rc = ldap_delete_s(ldap_handle, distinguished_name))
5581     {
5582       com_err(whoami, 0, "Unable to process user %s : %s",
5583               user_name, ldap_err2string(rc));
5584     }
5585
5586   /* Need to add code to delete mit.edu contact */
5587   
5588   if (Exchange)
5589     {
5590       sprintf(temp, "cn=%s@mit.edu,%s,%s", user_name, contact_ou, dn_path);
5591
5592       if(rc = ldap_delete_s(ldap_handle, temp))
5593         {
5594           com_err(whoami, 0, "Unable to delete user contact for %s",
5595                   user_name);
5596         }
5597     }
5598
5599  cleanup:
5600   linklist_free(group_base);
5601
5602   return(0);
5603 }
5604
5605 void linklist_free(LK_ENTRY *linklist_base)
5606 {
5607   LK_ENTRY *linklist_previous;
5608
5609   while (linklist_base != NULL)
5610     {
5611       if (linklist_base->dn != NULL)
5612         free(linklist_base->dn);
5613
5614       if (linklist_base->attribute != NULL)
5615         free(linklist_base->attribute);
5616
5617       if (linklist_base->value != NULL)
5618         free(linklist_base->value);
5619
5620       if (linklist_base->member != NULL)
5621         free(linklist_base->member);
5622
5623       if (linklist_base->type != NULL)
5624         free(linklist_base->type);
5625
5626       if (linklist_base->list != NULL)
5627         free(linklist_base->list);
5628
5629       linklist_previous = linklist_base;
5630       linklist_base = linklist_previous->next;
5631       free(linklist_previous);
5632     }
5633 }
5634
5635 void free_values(char **modvalues)
5636 {
5637   int i;
5638
5639   i = 0;
5640
5641   if (modvalues != NULL)
5642     {
5643     while (modvalues[i] != NULL)
5644       {
5645         free(modvalues[i]);
5646         modvalues[i] = NULL;
5647         ++i;
5648       }
5649     free(modvalues);
5650   }
5651 }
5652
5653 static int illegalchars[] = {
5654   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
5655   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
5656   1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, /* SPACE - / */
5657   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 0 - ? */
5658   0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
5659   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* P - _ */
5660   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
5661   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
5662   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5663   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5664   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5665   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5666   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5667   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5668   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5669   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5670 };
5671
5672 static int illegalchars_ldap[] = {
5673   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
5674   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
5675   0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, /* SPACE - / */
5676   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, /* 0 - ? */
5677   0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
5678   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, /* P - _ */
5679   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
5680   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
5681   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5682   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5683   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5684   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5685   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5686   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5687   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5688   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5689 };
5690
5691 int check_string(char *s)
5692 {
5693   char  character;
5694   char  *string;
5695
5696   string = s;
5697
5698   for (; *s; s++)
5699     {
5700       character = *s;
5701
5702       if (isupper(character))
5703         character = tolower(character);
5704
5705       if(ActiveDirectory)
5706         {
5707           if (illegalchars[(unsigned) character])
5708             {
5709               com_err(whoami, 0, "Found illegal char '%c' (%d) in string %s",
5710                       character, (unsigned) character, string);
5711               return 0;
5712             }
5713         }
5714       else
5715         {
5716           if (illegalchars_ldap[(unsigned) character])
5717             {
5718               com_err(whoami, 0, "Found illegal char '%c' (%d) in string %s",
5719                       character, (unsigned) character, string);
5720               return 0;
5721             }
5722         }
5723     }
5724
5725   return(1);
5726 }
5727
5728 int check_container_name(char *s)
5729 {
5730   char  character;
5731
5732   for (; *s; s++)
5733     {
5734       character = *s;
5735
5736       if (isupper(character))
5737         character = tolower(character);
5738
5739       if (character == ' ')
5740         continue;
5741
5742       if (illegalchars[(unsigned) character])
5743         return 0;
5744     }
5745
5746   return(1);
5747 }
5748
5749 int mr_connect_cl(char *server, char *client, int version, int auth)
5750 {
5751   int   status;
5752   char  *motd;
5753   char  temp[128];
5754
5755   status = mr_connect(server);
5756
5757   if (status)
5758     {
5759       com_err(whoami, status, "while connecting to Moira");
5760       return status;
5761     }
5762
5763   status = mr_motd(&motd);
5764
5765   if (status)
5766     {
5767       mr_disconnect();
5768       com_err(whoami, status, "while checking server status");
5769       return status;
5770     }
5771
5772   if (motd)
5773     {
5774       sprintf(temp, "The Moira server is currently unavailable: %s", motd);
5775       com_err(whoami, status, temp);
5776       mr_disconnect();
5777       return status;
5778     }
5779
5780   status = mr_version(version);
5781
5782   if (status)
5783     {
5784       if (status == MR_UNKNOWN_PROC)
5785         {
5786           if (version > 2)
5787             status = MR_VERSION_HIGH;
5788           else
5789             status = MR_SUCCESS;
5790         }
5791
5792       if (status == MR_VERSION_HIGH)
5793         {
5794           com_err(whoami, 0, "Warning: This client is running newer code "
5795                   "than the server.");
5796                   com_err(whoami, 0, "Some operations may not work.");
5797         }
5798       else if (status && status != MR_VERSION_LOW)
5799         {
5800           com_err(whoami, status, "while setting query version number.");
5801           mr_disconnect();
5802           return status;
5803         }
5804     }
5805
5806   if (auth)
5807     {
5808       status = mr_krb5_auth(client);
5809       if (status)
5810         {
5811           com_err(whoami, status, "while authenticating to Moira.");
5812           mr_disconnect();
5813           return status;
5814         }
5815     }
5816   
5817   return MR_SUCCESS;
5818 }
5819
5820 void AfsToWinAfs(char* path, char* winPath)
5821 {
5822   char* pathPtr;
5823   char* winPathPtr;
5824   strcpy(winPath, WINAFS);
5825   pathPtr = path + strlen(AFS);
5826   winPathPtr = winPath + strlen(WINAFS);
5827   
5828   while (*pathPtr)
5829     {
5830       if (*pathPtr == '/')
5831         *winPathPtr = '\\';
5832       else
5833         *winPathPtr = *pathPtr;
5834       
5835       pathPtr++;
5836       winPathPtr++;
5837     }
5838 }
5839
5840 int GetAceInfo(int ac, char **av, void *ptr)
5841 {
5842   char **call_args;
5843   int   security_flag;
5844
5845   call_args = ptr;
5846   
5847   strcpy(call_args[0], av[L_ACE_TYPE]);
5848   strcpy(call_args[1], av[L_ACE_NAME]);
5849   security_flag = 0;
5850   get_group_membership(call_args[2], call_args[3], &security_flag, av);
5851   return(LDAP_SUCCESS);  
5852 }
5853
5854 int checkADname(LDAP *ldap_handle, char *dn_path, char *Name)
5855 {
5856   char filter[128];
5857   char *attr_array[3];
5858   int  group_count;
5859   int  rc;
5860   LK_ENTRY  *group_base;
5861   
5862   group_count = 0;
5863   group_base = NULL;
5864   
5865   sprintf(filter, "(sAMAccountName=%s)", Name);
5866   attr_array[0] = "sAMAccountName";
5867   attr_array[1] = NULL;
5868
5869   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
5870                            &group_base, &group_count, 
5871                            LDAP_SCOPE_SUBTREE)) != 0)
5872     {
5873       com_err(whoami, 0, "Unable to process ACE name %s : %s",
5874               Name, ldap_err2string(rc));
5875       return(1);
5876     }
5877
5878   linklist_free(group_base);
5879   group_base = NULL;
5880
5881   if (group_count == 0)
5882     return(0);
5883   
5884   return(1);
5885 }
5886
5887 #define MAX_ACE 7
5888
5889 int ProcessAce(LDAP *ldap_handle, char *dn_path, char *Name, char *Type, 
5890                int UpdateGroup, int *ProcessGroup, char *maillist)
5891 {
5892   char  *av[2];
5893   char  GroupName[256];
5894   char  *call_args[7];
5895   int   rc;
5896   char  *AceInfo[4];
5897   char  AceType[32];
5898   char  AceName[128];
5899   char  AceMembership[2];
5900   char  AceOu[256];
5901   char  temp[128];
5902   char  *save_argv[U_END];
5903
5904   if (!SetGroupAce)
5905     {
5906       com_err(whoami, 0, "ProcessAce disabled, skipping");
5907       return(0);
5908     }
5909
5910   strcpy(GroupName, Name);
5911   
5912   if (strcasecmp(Type, "LIST"))
5913     return(1);
5914
5915   while (1)
5916     {
5917       av[0] = GroupName;
5918       AceInfo[0] = AceType;
5919       AceInfo[1] = AceName;
5920       AceInfo[2] = AceMembership;
5921       AceInfo[3] = AceOu;
5922       memset(AceType, '\0', sizeof(AceType));
5923       memset(AceName, '\0', sizeof(AceName));
5924       memset(AceMembership, '\0', sizeof(AceMembership));
5925       memset(AceOu, '\0', sizeof(AceOu));
5926       callback_rc = 0;
5927     
5928       if (rc = mr_query("get_list_info", 1, av, GetAceInfo, AceInfo))
5929         { 
5930           if(rc != MR_NO_MATCH)
5931             com_err(whoami, 0, "Unable to get ACE info for list %s : %s", 
5932                     GroupName, error_message(rc));
5933
5934           return(1);
5935         }
5936
5937       if (callback_rc)
5938         {
5939           com_err(whoami, 0, "Unable to get ACE info for list %s", GroupName);
5940           return(1);
5941         }
5942
5943       if ((strcasecmp(AceType, "USER")) && (strcasecmp(AceType, "LIST")))
5944         return(0);
5945
5946       strcpy(temp, AceName);
5947
5948       if (!strcasecmp(AceType, "LIST"))
5949         sprintf(temp, "%s%s", AceName, group_suffix);
5950
5951       if (!UpdateGroup)
5952         {
5953           if (checkADname(ldap_handle, dn_path, temp))
5954               return(0);
5955
5956           (*ProcessGroup) = 1;
5957         }
5958
5959       if (!strcasecmp(AceInfo[0], "LIST"))
5960         {
5961           if (make_new_group(ldap_handle, dn_path, "", AceName, AceOu, 
5962                              AceMembership, 0, UpdateGroup, maillist))
5963             return(1);
5964
5965           populate_group(ldap_handle, dn_path, AceName, AceOu, AceMembership,
5966                          0, "");
5967         }
5968       else if (!strcasecmp(AceInfo[0], "USER"))
5969         {
5970           av[0] = AceName;
5971           call_args[0] = (char *)ldap_handle;
5972           call_args[1] = dn_path;
5973           call_args[2] = "";
5974           call_args[3] = NULL;
5975           callback_rc = 0;
5976
5977           if(!strcasecmp(AceName, PRODUCTION_PRINCIPAL) ||
5978              !strcasecmp(AceName, TEST_PRINCIPAL))
5979             {
5980               return(1);
5981             }
5982
5983           if (rc = mr_query("get_user_account_by_login", 1, av, 
5984                             save_query_info, save_argv))
5985             {
5986               com_err(whoami, 0, "Unable to process user ACE %s for group %s.",
5987                       AceName, Name);
5988               return(1);
5989             }
5990
5991           if (rc = user_create(U_END, save_argv, call_args)) 
5992             {
5993               com_err(whoami, 0, "Unable to process user ACE %s for group %s.",
5994                       AceName, Name);
5995               return(1);
5996             }
5997           
5998           if (callback_rc)
5999             {
6000               com_err(whoami, 0, "Unable to process user Ace %s for group %s",
6001                       AceName, Name);
6002               return(1);
6003             }
6004
6005           return(0);
6006         }
6007       else
6008         return(1);
6009
6010       if (!strcasecmp(AceType, "LIST"))
6011         {
6012           if (!strcasecmp(GroupName, AceName))
6013             return(0);
6014         }
6015
6016       strcpy(GroupName, AceName);
6017     }
6018   
6019   return(1);
6020 }
6021
6022 int make_new_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
6023                    char *group_name, char *group_ou, char *group_membership, 
6024                    int group_security_flag, int updateGroup, char *maillist)
6025 {
6026   char  *av[3];
6027   char  *call_args[8];
6028   int   rc;
6029   LK_ENTRY  *group_base;
6030   int  group_count;
6031   char filter[128];
6032   char *attr_array[3];
6033
6034   av[0] = group_name;
6035   call_args[0] = (char *)ldap_handle;
6036   call_args[1] = dn_path;
6037   call_args[2] = group_name;
6038   call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
6039   call_args[4] = (char *)updateGroup;
6040   call_args[5] = MoiraId;
6041   call_args[6] = "0";
6042   call_args[7] = NULL;
6043   callback_rc = 0;
6044
6045   group_count = 0;
6046   group_base = NULL;
6047
6048   if (rc = mr_query("get_list_info", 1, av, group_create, call_args))
6049     {
6050       moira_disconnect();
6051       com_err(whoami, 0, "Unable to create list %s : %s", group_name, 
6052               error_message(rc));
6053       return(rc);
6054     }
6055
6056   if (callback_rc)
6057     {
6058       moira_disconnect();
6059       com_err(whoami, 0, "Unable to create list %s", group_name);
6060       return(callback_rc);
6061     }
6062
6063   return(0);
6064 }
6065
6066 int populate_group(LDAP *ldap_handle, char *dn_path, char *group_name, 
6067                    char *group_ou, char *group_membership, 
6068                    int group_security_flag, char *MoiraId)
6069 {
6070   char      *av[3];
6071   char      *call_args[7];
6072   char      *pUserOu;
6073   LK_ENTRY  *ptr;
6074   int       rc;
6075   char      member[512];
6076   char      *s;
6077   char      **members;
6078   int       i = 0;
6079   int       j = 0;
6080   int       n = 0;
6081   char      group_dn[512];
6082   LDAPMod   *mods[20];
6083   char      *member_v[] = {NULL, NULL};
6084   char      *save_argv[U_END];
6085   char      machine_ou[256];
6086   char      NewMachineName[1024];
6087
6088   com_err(whoami, 0, "Populating group %s", group_name);
6089   av[0] = group_name;
6090   call_args[0] = (char *)ldap_handle;
6091   call_args[1] = dn_path;
6092   call_args[2] = group_name;
6093   call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS | 
6094                           MOIRA_MACHINE);
6095   call_args[4] = NULL;
6096   member_base = NULL;
6097
6098   if (rc = mr_query("get_end_members_of_list", 1, av,
6099                     member_list_build, call_args))
6100     {
6101       if(rc == MR_LIST)
6102         return(0);
6103       
6104       com_err(whoami, 0, "Unable to populate list %s : %s", 
6105               group_name, error_message(rc));
6106       return(3);
6107     }
6108
6109   members = (char **)malloc(sizeof(char *) * 2);
6110
6111   if (member_base != NULL)
6112     {
6113       ptr = member_base;
6114
6115       while (ptr != NULL)
6116         {
6117           if (!strcasecmp(ptr->type, "LIST"))
6118             {
6119               ptr = ptr->next;
6120               continue;
6121             }
6122           
6123           if (!strcasecmp(ptr->type, "MACHINE") && !ProcessMachineContainer)
6124             {
6125               ptr = ptr->next;
6126               continue;
6127             }
6128             
6129           if(!strcasecmp(ptr->type, "USER"))
6130             {
6131               if(!strcasecmp(ptr->member, PRODUCTION_PRINCIPAL) ||
6132                  !strcasecmp(ptr->member, TEST_PRINCIPAL))
6133                 {
6134                   ptr = ptr->next;
6135                   continue;
6136                 }
6137
6138               if ((rc = check_user(ldap_handle, dn_path, ptr->member,
6139                                    "")) == AD_NO_USER_FOUND)
6140                 {
6141                   com_err(whoami, 0, "creating user %s", ptr->member);
6142
6143                   av[0] = ptr->member;
6144                   call_args[0] = (char *)ldap_handle;
6145                   call_args[1] = dn_path;
6146                   call_args[2] = "";
6147                   call_args[3] = NULL;
6148                   callback_rc = 0;
6149                   
6150                   if (rc = mr_query("get_user_account_by_login", 1, av, 
6151                                     save_query_info, save_argv))
6152                     {
6153                       com_err(whoami, 0, "Unable to create user %s " 
6154                               "while populating group %s.", ptr->member,
6155                               group_name);
6156
6157                       return(3);
6158                     }
6159
6160                   if (rc = user_create(U_END, save_argv, call_args)) 
6161                     {
6162                       com_err(whoami, 0, "Unable to create user %s "
6163                               "while populating group %s.", ptr->member,
6164                               group_name);
6165                       
6166                       return(3);
6167                     }
6168           
6169                   if (callback_rc)
6170                     {
6171                       com_err(whoami, 0, "Unable to create user %s "
6172                               "while populating group %s", ptr->member, 
6173                               group_name);
6174
6175                       return(3);
6176                     }
6177                 }
6178
6179               pUserOu = user_ou;
6180                   
6181               if(ActiveDirectory) 
6182                 {
6183                   sprintf(member, "cn=%s,%s,%s", ptr->member, pUserOu, 
6184                           dn_path);
6185                 }
6186               else 
6187                 {
6188                   sprintf(member, "uid=%s,%s,%s", ptr->member, pUserOu, 
6189                           dn_path);
6190                 }
6191             }
6192           else if (!strcasecmp(ptr->type, "STRING"))
6193             {
6194               if (contact_create(ldap_handle, dn_path, ptr->member,
6195                                  contact_ou))
6196                 return(3);
6197
6198               pUserOu = contact_ou;
6199               sprintf(member, "cn=%s,%s,%s", escape_string(ptr->member), 
6200                       pUserOu, dn_path);
6201             }
6202           else if (!strcasecmp(ptr->type, "KERBEROS"))
6203             {
6204               if (contact_create(ldap_handle, dn_path, ptr->member, 
6205                                  kerberos_ou))
6206                 return(3);
6207
6208               pUserOu = kerberos_ou;
6209               sprintf(member, "cn=%s,%s,%s", escape_string(ptr->member), 
6210                       pUserOu, dn_path);
6211             }
6212           else if (!strcasecmp(ptr->type, "MACHINE"))
6213             {
6214               memset(machine_ou, '\0', sizeof(machine_ou));
6215               memset(NewMachineName, '\0', sizeof(NewMachineName));
6216
6217               if (!get_machine_ou(ldap_handle, dn_path, ptr->member,
6218                                  machine_ou, NewMachineName))
6219                 {
6220                   pUserOu = machine_ou;
6221                   sprintf(member, "cn=%s,%s,%s", NewMachineName, pUserOu,
6222                           dn_path);
6223                 }
6224               else
6225                 {
6226                   ptr = ptr->next;                  
6227                   continue;
6228                 }
6229             }
6230
6231           if(i > 1) 
6232             members = (char **)realloc(members, ((i + 2) * sizeof(char *)));
6233           members[i++] = strdup(member);
6234
6235           ptr = ptr->next;
6236         }
6237     
6238       linklist_free(member_base);
6239       member_base = NULL;
6240     }
6241
6242   members[i] = NULL;
6243
6244   sprintf(group_dn, "cn=%s,%s,%s", group_name, group_ou, dn_path);
6245
6246   if(GroupPopulateDelete)
6247     {
6248       n = 0;
6249       ADD_ATTR("member", member_v, LDAP_MOD_REPLACE);
6250       mods[n] = NULL;
6251       
6252       if ((rc = ldap_modify_s(ldap_handle, group_dn, 
6253                               mods)) != LDAP_SUCCESS)
6254         {
6255           com_err(whoami, 0,
6256                   "Unable to populate group membership for %s: %s",
6257                   group_dn, ldap_err2string(rc));
6258         }
6259   
6260       for (i = 0; i < n; i++)
6261         free(mods[i]);
6262     }
6263
6264   n = 0;
6265   ADD_ATTR("member", members, LDAP_MOD_REPLACE);
6266   mods[n] = NULL;
6267
6268   if ((rc = ldap_modify_s(ldap_handle, group_dn, 
6269                           mods)) != LDAP_SUCCESS)
6270     {
6271       com_err(whoami, 0,
6272               "Unable to populate group membership for %s: %s",
6273               group_dn, ldap_err2string(rc));
6274     }
6275   
6276   for (i = 0; i < n; i++)
6277     free(mods[i]);
6278     
6279   free(members);
6280
6281   return(0);
6282 }
6283
6284 int process_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
6285                   char *group_name, char *group_ou, char *group_membership, 
6286                   int group_security_flag, int type, char *maillist)
6287 {
6288   char      before_desc[512];
6289   char      before_name[256];
6290   char      before_group_ou[256];
6291   char      before_group_membership[2];
6292   char      distinguishedName[256];
6293   char      ad_distinguishedName[256];
6294   char      filter[128];
6295   char      *attr_array[3];
6296   int       before_security_flag;
6297   int       group_count;
6298   int       rc;
6299   LK_ENTRY  *group_base;
6300   LK_ENTRY  *ptr;
6301   char      ou_both[512];
6302   char      ou_security[512];
6303   char      ou_distribution[512];
6304   char      ou_neither[512];
6305   char      group_dn[512];
6306
6307   memset(ad_distinguishedName, '\0', sizeof(ad_distinguishedName));
6308   sprintf(distinguishedName, "CN=%s,%s,%s", group_name, group_ou, dn_path);
6309
6310   memset(filter, '\0', sizeof(filter));
6311   group_base = NULL;
6312   group_count = 0;
6313
6314   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
6315                         "*", MoiraId, 
6316                         "samAccountName", &group_base, 
6317                         &group_count, filter))
6318     return(rc);
6319
6320   if (type == CHECK_GROUPS)
6321     {
6322       if (group_count == 1)
6323         {
6324           strcpy(group_dn, group_base->dn);
6325
6326           if (!strcasecmp(group_dn, distinguishedName))
6327             {
6328               linklist_free(group_base);
6329               return(0);
6330             }
6331         }
6332
6333       linklist_free(group_base);
6334
6335       if (group_count == 0)
6336         return(AD_NO_GROUPS_FOUND);
6337
6338       if (group_count == 1)
6339         return(AD_WRONG_GROUP_DN_FOUND);
6340
6341       return(AD_MULTIPLE_GROUPS_FOUND);
6342     }
6343
6344   if (group_count == 0)
6345     {
6346       return(AD_NO_GROUPS_FOUND);
6347     }
6348
6349   if (group_count > 1)
6350     {
6351       ptr = group_base;
6352
6353       strcpy(group_dn, ptr->dn);
6354
6355       while (ptr != NULL)
6356         {
6357           if (!strcasecmp(group_dn, ptr->value))
6358             break;
6359
6360           ptr = ptr->next;
6361         }
6362
6363       if (ptr == NULL)
6364         {
6365           com_err(whoami, 0, "%d groups with moira id = %s", group_count, 
6366                   MoiraId);
6367           ptr = group_base;
6368
6369           while (ptr != NULL)
6370             {
6371               com_err(whoami, 0, "%s with moira id = %s", ptr->value, MoiraId);
6372               ptr = ptr->next;
6373             }
6374
6375           linklist_free(group_base);
6376           return(AD_MULTIPLE_GROUPS_FOUND);
6377         }
6378
6379       ptr = group_base;
6380
6381       while (ptr != NULL)
6382         {
6383           strcpy(group_dn, ptr->dn);
6384
6385           if (strcasecmp(group_dn, ptr->value))
6386             rc = ldap_delete_s(ldap_handle, ptr->value);
6387
6388           ptr = ptr->next;
6389         }
6390
6391       linklist_free(group_base);
6392       memset(filter, '\0', sizeof(filter));
6393       group_base = NULL;
6394       group_count = 0;
6395
6396       if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
6397                             "*", MoiraId, 
6398                             "samAccountName", &group_base, 
6399                             &group_count, filter))
6400         return(rc);
6401
6402       if (group_count == 0)
6403         return(AD_NO_GROUPS_FOUND);
6404
6405       if (group_count > 1)
6406         return(AD_MULTIPLE_GROUPS_FOUND);
6407     }
6408
6409   strcpy(ad_distinguishedName, group_base->dn);
6410   linklist_free(group_base);
6411   group_base = NULL;
6412   group_count = 0;
6413
6414   attr_array[0] = "sAMAccountName";
6415   attr_array[1] = NULL;
6416   
6417   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6418                            &group_base, &group_count, 
6419                            LDAP_SCOPE_SUBTREE)) != 0)
6420     {
6421       com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6422               MoiraId, ldap_err2string(rc));
6423       return(rc);
6424     }
6425   
6426   sprintf(filter, "(sAMAccountName=%s)", group_base->value);
6427
6428   if (!strcasecmp(ad_distinguishedName, distinguishedName))
6429     {
6430       linklist_free(group_base);
6431       group_base = NULL;
6432       group_count = 0;
6433       return(0);
6434     }
6435
6436   linklist_free(group_base);
6437   group_base = NULL;
6438   group_count = 0;
6439   memset(ou_both, '\0', sizeof(ou_both));
6440   memset(ou_security, '\0', sizeof(ou_security));
6441   memset(ou_distribution, '\0', sizeof(ou_distribution));
6442   memset(ou_neither, '\0', sizeof(ou_neither));
6443   memset(before_name, '\0', sizeof(before_name));
6444   memset(before_desc, '\0', sizeof(before_desc));
6445   memset(before_group_membership, '\0', sizeof(before_group_membership));
6446   
6447   attr_array[0] = "name";
6448   attr_array[1] = NULL;
6449
6450   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6451                            &group_base, &group_count, 
6452                            LDAP_SCOPE_SUBTREE)) != 0)
6453     {
6454       com_err(whoami, 0, "Unable to get list name with MoiraId = %s: %s",
6455               MoiraId, ldap_err2string(rc));
6456       return(rc);
6457     }
6458
6459   strcpy(before_name, group_base->value);
6460   linklist_free(group_base);
6461   group_base = NULL;
6462   group_count = 0;
6463
6464   attr_array[0] = "description";
6465   attr_array[1] = NULL;
6466   
6467   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6468                            &group_base, &group_count, 
6469                            LDAP_SCOPE_SUBTREE)) != 0)
6470     {
6471       com_err(whoami, 0, 
6472               "Unable to get list description with MoiraId = %s: %s",
6473               MoiraId, ldap_err2string(rc));
6474       return(rc);
6475     }
6476
6477   if (group_count != 0)
6478     {
6479       strcpy(before_desc, group_base->value);
6480       linklist_free(group_base);
6481       group_base = NULL;
6482       group_count = 0;
6483     }
6484  
6485   change_to_lower_case(ad_distinguishedName);  
6486   strcpy(ou_both, group_ou_both);
6487   change_to_lower_case(ou_both);
6488   strcpy(ou_security, group_ou_security);
6489   change_to_lower_case(ou_security);
6490   strcpy(ou_distribution, group_ou_distribution);
6491   change_to_lower_case(ou_distribution);
6492   strcpy(ou_neither, group_ou_neither);
6493   change_to_lower_case(ou_neither);
6494
6495   if (strstr(ad_distinguishedName, ou_both))
6496     {
6497       strcpy(before_group_ou, group_ou_both);
6498       before_group_membership[0] = 'B';
6499       before_security_flag = 1;
6500     }
6501   else if (strstr(ad_distinguishedName, ou_security))
6502     {
6503       strcpy(before_group_ou, group_ou_security);
6504       before_group_membership[0] = 'S';
6505       before_security_flag = 1;
6506     }
6507   else if (strstr(ad_distinguishedName, ou_distribution))
6508     {
6509       strcpy(before_group_ou, group_ou_distribution);
6510       before_group_membership[0] = 'D';
6511       before_security_flag = 0;
6512     }
6513   else if (strstr(ad_distinguishedName, ou_neither))
6514     {
6515       strcpy(before_group_ou, group_ou_neither);
6516       before_group_membership[0] = 'N';
6517       before_security_flag = 0;
6518     }
6519   else
6520     return(AD_NO_OU_FOUND);
6521
6522   rc = group_rename(ldap_handle, dn_path, before_name, 
6523                     before_group_membership, 
6524                     before_group_ou, before_security_flag, before_desc,
6525                     group_name, group_membership, group_ou, 
6526                     group_security_flag,
6527                     before_desc, MoiraId, filter, maillist);
6528
6529   return(rc);
6530 }
6531
6532 void change_to_lower_case(char *ptr)
6533 {
6534   int i;
6535
6536   for (i = 0; i < (int)strlen(ptr); i++)
6537     {
6538       ptr[i] = tolower(ptr[i]);
6539     }
6540 }
6541
6542 int ad_get_group(LDAP *ldap_handle, char *dn_path, 
6543                  char *group_name, char *group_membership, 
6544                  char *MoiraId, char *attribute,
6545                  LK_ENTRY **linklist_base, int *linklist_count,
6546                  char *rFilter)
6547 {
6548   LK_ENTRY  *pPtr;
6549   char  filter[128];
6550   char  *attr_array[3];
6551   char  *dn;
6552   int   rc;
6553
6554   (*linklist_base) = NULL;
6555   (*linklist_count) = 0;
6556
6557   if (strlen(rFilter) != 0)
6558     {
6559       strcpy(filter, rFilter);
6560       attr_array[0] = attribute;
6561       attr_array[1] = NULL;
6562       
6563       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6564                                linklist_base, linklist_count, 
6565                                LDAP_SCOPE_SUBTREE)) != 0)
6566         {
6567           com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6568                   MoiraId, ldap_err2string(rc));
6569          return(rc);
6570        }
6571
6572     if ((*linklist_count) == 1)
6573       {
6574         strcpy(rFilter, filter);
6575         return(0);
6576       }
6577     }
6578
6579   linklist_free((*linklist_base));
6580   (*linklist_base) = NULL;
6581   (*linklist_count) = 0;
6582
6583   if (strlen(MoiraId) != 0)
6584     {
6585       sprintf(filter, "(&(objectClass=group)(mitMoiraId=%s))", MoiraId);
6586
6587       attr_array[0] = attribute;
6588       attr_array[1] = NULL;
6589
6590       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6591                                linklist_base, linklist_count, 
6592                                LDAP_SCOPE_SUBTREE)) != 0)
6593         {
6594           com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6595                   MoiraId, ldap_err2string(rc));
6596          return(rc);
6597        }
6598     }
6599
6600   if ((*linklist_count) > 1)
6601     {
6602       com_err(whoami, 0, "multiple groups with mitMoiraId = %s", MoiraId);
6603       pPtr = (*linklist_base);
6604
6605       while (pPtr)
6606         {
6607           com_err(whoami, 0, "groups %s has mitMoiraId = %s", pPtr->value, 
6608                   MoiraId);
6609           pPtr = pPtr->next;
6610         }
6611
6612       linklist_free((*linklist_base));
6613       (*linklist_base) = NULL;
6614       (*linklist_count) = 0;
6615     }
6616
6617   if ((*linklist_count) == 1)
6618     {
6619
6620       pPtr = (*linklist_base);
6621       dn = strdup(pPtr->dn);
6622       dn += 3;
6623
6624       if (!memcmp(dn, group_name, strlen(group_name)))
6625         {
6626           strcpy(rFilter, filter);
6627           return(0);
6628         }
6629     }
6630
6631   linklist_free((*linklist_base));
6632   (*linklist_base) = NULL;
6633   (*linklist_count) = 0;
6634   sprintf(filter, "(sAMAccountName=%s%s)", group_name, group_suffix);
6635
6636   attr_array[0] = attribute;
6637   attr_array[1] = NULL;
6638
6639   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6640                            linklist_base, linklist_count, 
6641                            LDAP_SCOPE_SUBTREE)) != 0)
6642     {
6643       com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6644               MoiraId, ldap_err2string(rc));
6645       return(rc);
6646     }
6647
6648   if ((*linklist_count) == 1)
6649     {
6650       strcpy(rFilter, filter);
6651       return(0);
6652     }
6653
6654   return(0);
6655 }
6656
6657 int check_user(LDAP *ldap_handle, char *dn_path, char *UserName, char *MoiraId)
6658 {
6659   char filter[128];
6660   char *attr_array[3];
6661   char SamAccountName[64];
6662   int  group_count;
6663   int  rc;
6664   LK_ENTRY  *group_base;
6665   LK_ENTRY  *gPtr;
6666
6667   group_count = 0;
6668   group_base = NULL;
6669
6670   if (strlen(MoiraId) != 0)
6671     {
6672       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
6673
6674       attr_array[0] = "sAMAccountName";
6675       attr_array[1] = NULL;
6676       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6677                                &group_base, &group_count, 
6678                                LDAP_SCOPE_SUBTREE)) != 0)
6679         {
6680           com_err(whoami, 0, "Unable to process user %s : %s",
6681                   UserName, ldap_err2string(rc));
6682           return(rc);
6683         }
6684
6685       if (group_count > 1)
6686         {
6687           com_err(whoami, 0, "multiple users exist with MoiraId = %s",
6688                   MoiraId);
6689           gPtr = group_base;
6690
6691           while (gPtr)
6692             {
6693               com_err(whoami, 0, "user %s exist with MoiraId = %s",
6694                       gPtr->value, MoiraId);
6695               gPtr = gPtr->next;
6696             }
6697         }
6698     }
6699
6700   if (group_count != 1)
6701     {
6702       linklist_free(group_base);
6703       group_count = 0;
6704       group_base = NULL;
6705       sprintf(filter, "(sAMAccountName=%s)", UserName);
6706       attr_array[0] = "sAMAccountName";
6707       attr_array[1] = NULL;
6708
6709       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6710                                &group_base, &group_count, 
6711                                LDAP_SCOPE_SUBTREE)) != 0)
6712         {
6713           com_err(whoami, 0, "Unable to process user %s : %s",
6714                   UserName, ldap_err2string(rc));
6715           return(rc);
6716         }
6717     }
6718
6719   if (group_count != 1)
6720     {
6721       linklist_free(group_base);
6722       return(AD_NO_USER_FOUND);
6723     }
6724
6725   strcpy(SamAccountName, group_base->value);
6726   linklist_free(group_base);
6727   group_count = 0;
6728   rc = 0;
6729
6730   if (strcmp(SamAccountName, UserName))
6731     {
6732       com_err(whoami, 0, 
6733               "User object %s with MoiraId %s has mismatched usernames " 
6734               "(LDAP username %s, Moira username %s)", SamAccountName,
6735               MoiraId, SamAccountName, UserName);
6736     }
6737
6738   return(0);
6739 }
6740
6741 void container_get_dn(char *src, char *dest)
6742 {
6743   char *sPtr;
6744   char *array[20];
6745   char name[256];
6746   int  n;
6747
6748   memset(array, '\0', 20 * sizeof(array[0]));
6749
6750   if (strlen(src) == 0)
6751     return;
6752
6753   strcpy(name, src);
6754   sPtr = name;
6755   n = 0;
6756   array[n] = name;
6757   ++n;
6758
6759   while (*sPtr)
6760     {
6761       if ((*sPtr) == '/')
6762         {
6763           (*sPtr) = '\0';
6764           ++sPtr;
6765           array[n] = sPtr;
6766           ++n;
6767         }
6768       else
6769         ++sPtr;
6770     }
6771
6772   strcpy(dest, "OU=");
6773
6774   while (n != 0)
6775     {
6776       strcat(dest, array[n-1]);
6777       --n;
6778       if (n > 0)
6779         {
6780           strcat(dest, ",OU=");
6781         }
6782     }
6783
6784   return;
6785 }
6786
6787 void container_get_name(char *src, char *dest)
6788 {
6789   char *sPtr;
6790   char *dPtr;
6791
6792   if (strlen(src) == 0)
6793     return;
6794
6795   sPtr = src;
6796   dPtr = src;
6797
6798   while (*sPtr)
6799     {
6800       if ((*sPtr) == '/')
6801         {
6802           dPtr = sPtr;
6803           ++dPtr;
6804         }
6805       ++sPtr;
6806     }
6807
6808   strcpy(dest, dPtr);
6809   return;
6810 }
6811
6812 void container_check(LDAP *ldap_handle, char *dn_path, char *name)
6813 {
6814   char cName[256];
6815   char *av[7];
6816   int  i;
6817   int  rc;
6818
6819   strcpy(cName, name);
6820
6821   for (i = 0; i < (int)strlen(cName); i++)
6822     {
6823       if (cName[i] == '/')
6824         {
6825           cName[i] = '\0';
6826           av[CONTAINER_NAME] = cName;
6827           av[CONTAINER_DESC] = "";
6828           av[CONTAINER_LOCATION] = "";
6829           av[CONTAINER_CONTACT] = "";
6830           av[CONTAINER_TYPE] = "";
6831           av[CONTAINER_ID] = "";
6832           av[CONTAINER_ROWID] = "";
6833           rc = container_create(ldap_handle, dn_path, 7, av);
6834
6835           if (rc == LDAP_SUCCESS)
6836             {
6837               com_err(whoami, 0, "container %s created without a mitMoiraId", 
6838                       cName);
6839             }
6840
6841           cName[i] = '/';
6842         }
6843     }
6844 }
6845
6846 int container_rename(LDAP *ldap_handle, char *dn_path, int beforec, 
6847                      char **before, int afterc, char **after)
6848 {
6849   char      dName[256];
6850   char      cName[256];
6851   char      new_cn[128];
6852   char      new_dn_path[256];
6853   char      temp[256];
6854   char      distinguishedName[256];
6855   char      *pPtr;
6856   int       rc;
6857   int       i;
6858
6859   memset(cName, '\0', sizeof(cName));
6860   container_get_name(after[CONTAINER_NAME], cName);
6861
6862   if (!check_container_name(cName))
6863     {
6864       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", 
6865               cName);
6866       return(AD_INVALID_NAME);
6867     }
6868
6869   memset(distinguishedName, '\0', sizeof(distinguishedName));
6870
6871   if (rc = container_get_distinguishedName(ldap_handle, dn_path, 
6872                                            distinguishedName, beforec, before))
6873     return(rc);
6874
6875   if (strlen(distinguishedName) == 0)
6876     {
6877       rc = container_create(ldap_handle, dn_path, afterc, after);
6878       return(rc);
6879     }
6880
6881   strcpy(temp, after[CONTAINER_NAME]);
6882   pPtr = temp;
6883
6884   for (i = 0; i < (int)strlen(temp); i++)
6885     {
6886       if (temp[i] == '/')
6887         {
6888           pPtr = &temp[i];
6889         }
6890     }
6891
6892   (*pPtr) = '\0';
6893
6894   container_get_dn(temp, dName);
6895
6896   if (strlen(temp) != 0)
6897     sprintf(new_dn_path, "%s,%s", dName, dn_path);
6898   else
6899     sprintf(new_dn_path, "%s", dn_path);
6900
6901   sprintf(new_cn, "OU=%s", cName);
6902
6903   container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
6904
6905   if ((rc = ldap_rename_s(ldap_handle, distinguishedName, new_cn, new_dn_path,
6906                           TRUE, NULL, NULL)) != LDAP_SUCCESS)
6907     {
6908       com_err(whoami, 0, "Unable to rename container from %s to %s : %s",
6909               before[CONTAINER_NAME], after[CONTAINER_NAME], 
6910               ldap_err2string(rc));
6911       return(rc);
6912     }
6913
6914   memset(dName, '\0', sizeof(dName));
6915   container_get_dn(after[CONTAINER_NAME], dName);
6916   rc = container_adupdate(ldap_handle, dn_path, dName, "", afterc, after);
6917
6918   return(rc);
6919 }
6920
6921 int container_delete(LDAP *ldap_handle, char *dn_path, int count, char **av)
6922 {
6923   char      distinguishedName[256];
6924   int       rc;
6925
6926   memset(distinguishedName, '\0', sizeof(distinguishedName));
6927
6928   if (rc = container_get_distinguishedName(ldap_handle, dn_path, 
6929                                            distinguishedName, count, av))
6930     return(rc);
6931
6932   if (strlen(distinguishedName) == 0)
6933     return(0);
6934
6935   if ((rc = ldap_delete_s(ldap_handle, distinguishedName)) != LDAP_SUCCESS)
6936     {
6937       if (rc == LDAP_NOT_ALLOWED_ON_NONLEAF)
6938         container_move_objects(ldap_handle, dn_path, distinguishedName);
6939       else
6940         com_err(whoami, 0, "Unable to delete container %s from directory : %s",
6941                 av[CONTAINER_NAME], ldap_err2string(rc));
6942     }
6943
6944   return(rc);
6945 }
6946
6947 int container_create(LDAP *ldap_handle, char *dn_path, int count, char **av)
6948 {
6949   char      *attr_array[3];
6950   LK_ENTRY  *group_base;
6951   int       group_count;
6952   LDAPMod   *mods[20];
6953   char      *objectClass_v[] = {"top", 
6954                            "organizationalUnit", 
6955                            NULL};
6956
6957   char *ou_v[] = {NULL, NULL};
6958   char *name_v[] = {NULL, NULL};
6959   char *moiraId_v[] = {NULL, NULL};
6960   char *desc_v[] = {NULL, NULL};
6961   char *managedBy_v[] = {NULL, NULL};
6962   char dName[256];
6963   char cName[256];
6964   char managedByDN[256];
6965   char filter[256];
6966   char temp[256];
6967   int  n;
6968   int  i;
6969   int  rc;
6970     
6971   memset(filter, '\0', sizeof(filter));
6972   memset(dName, '\0', sizeof(dName));
6973   memset(cName, '\0', sizeof(cName));
6974   memset(managedByDN, '\0', sizeof(managedByDN));
6975   container_get_dn(av[CONTAINER_NAME], dName);
6976   container_get_name(av[CONTAINER_NAME], cName);
6977
6978   if ((strlen(cName) == 0) || (strlen(dName) == 0))
6979     {
6980       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", 
6981               cName);
6982       return(AD_INVALID_NAME);
6983     }
6984
6985   if (!check_container_name(cName))
6986     {
6987       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", 
6988               cName);
6989       return(AD_INVALID_NAME);
6990     }
6991
6992   n = 0;
6993   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
6994   name_v[0] = cName;
6995   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
6996   ou_v[0] = cName;
6997   ADD_ATTR("ou", ou_v, LDAP_MOD_ADD);
6998
6999   if (strlen(av[CONTAINER_ROWID]) != 0)
7000     {
7001       moiraId_v[0] = av[CONTAINER_ROWID];
7002       ADD_ATTR("mitMoiraId", moiraId_v, LDAP_MOD_ADD);
7003     }
7004
7005   if (strlen(av[CONTAINER_DESC]) != 0)
7006     {
7007       desc_v[0] = av[CONTAINER_DESC];
7008       ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
7009     }
7010
7011   if ((strlen(av[CONTAINER_TYPE]) != 0) && (strlen(av[CONTAINER_ID]) != 0))
7012     {
7013       if (!strcasecmp(av[CONTAINER_TYPE], "KERBEROS"))
7014         {
7015           if (!contact_create(ldap_handle, dn_path, av[CONTAINER_ID], 
7016                               kerberos_ou))
7017             {
7018               sprintf(managedByDN, "CN=%s,%s,%s", av[CONTAINER_ID], 
7019                       kerberos_ou, dn_path);
7020               managedBy_v[0] = managedByDN;
7021               ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_ADD);
7022             }
7023         }
7024       else
7025         {
7026           if (!strcasecmp(av[CONTAINER_TYPE], "USER"))
7027             {
7028               sprintf(filter, "(&(cn=%s)(&(objectCategory=person)"
7029                       "(objectClass=user)))", av[CONTAINER_ID]);
7030             }
7031
7032           if (!strcasecmp(av[CONTAINER_TYPE], "LIST"))
7033             {
7034               sprintf(filter, "(&(objectClass=group)(cn=%s))", 
7035                       av[CONTAINER_ID]);
7036             }
7037
7038           if (strlen(filter) != 0)
7039             {
7040               attr_array[0] = "distinguishedName";
7041               attr_array[1] = NULL;
7042               group_count = 0;
7043               group_base = NULL;
7044               if ((rc = linklist_build(ldap_handle, dn_path, filter, 
7045                                        attr_array, 
7046                                        &group_base, &group_count, 
7047                                        LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7048                 {
7049                   if (group_count == 1)
7050                     {
7051                       strcpy(managedByDN, group_base->value);
7052                       managedBy_v[0] = managedByDN;
7053                       ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_ADD);
7054                     }
7055                   linklist_free(group_base);
7056                   group_base = NULL;
7057                   group_count = 0;
7058                 }
7059             }
7060         }
7061     }
7062   
7063   mods[n] = NULL;
7064
7065   sprintf(temp, "%s,%s", dName, dn_path);
7066   rc = ldap_add_ext_s(ldap_handle, temp, mods, NULL, NULL);
7067   
7068   for (i = 0; i < n; i++)
7069     free(mods[i]);
7070   
7071   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
7072     {
7073       com_err(whoami, 0, "Unable to create container %s : %s",
7074               cName, ldap_err2string(rc));
7075       return(rc);
7076     }
7077
7078   if (rc == LDAP_ALREADY_EXISTS)
7079     {
7080       if (strlen(av[CONTAINER_ROWID]) != 0)
7081         rc = container_adupdate(ldap_handle, dn_path, dName, "", count, av);
7082     }
7083
7084   return(rc);
7085 }
7086
7087 int container_update(LDAP *ldap_handle, char *dn_path, int beforec, 
7088                      char **before, int afterc, char **after)
7089 {
7090   char distinguishedName[256];
7091   int  rc;
7092
7093   memset(distinguishedName, '\0', sizeof(distinguishedName));
7094
7095   if (rc = container_get_distinguishedName(ldap_handle, dn_path, 
7096                                            distinguishedName, afterc, after))
7097     return(rc);
7098
7099   if (strlen(distinguishedName) == 0)
7100     {
7101       rc = container_create(ldap_handle, dn_path, afterc, after);
7102       return(rc);
7103     }
7104   
7105   container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
7106   rc = container_adupdate(ldap_handle, dn_path, "", distinguishedName, afterc,
7107                           after);
7108
7109   return(rc);
7110 }
7111
7112 int container_get_distinguishedName(LDAP *ldap_handle, char *dn_path, 
7113                                     char *distinguishedName, int count, 
7114                                     char **av)
7115 {
7116   char      *attr_array[3];
7117   LK_ENTRY  *group_base;
7118   int       group_count;
7119   char      dName[256];
7120   char      cName[256];
7121   char      filter[512];
7122   int       rc;
7123
7124   memset(filter, '\0', sizeof(filter));
7125   memset(dName, '\0', sizeof(dName));
7126   memset(cName, '\0', sizeof(cName));
7127   container_get_dn(av[CONTAINER_NAME], dName);
7128   container_get_name(av[CONTAINER_NAME], cName);
7129
7130   if (strlen(dName) == 0)
7131     {
7132       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", 
7133               av[CONTAINER_NAME]);
7134       return(AD_INVALID_NAME);
7135     }
7136
7137   if (!check_container_name(cName))
7138     {
7139       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", 
7140               cName);
7141       return(AD_INVALID_NAME);
7142     }
7143   
7144   sprintf(filter, "(&(objectClass=organizationalUnit)(mitMoiraId=%s))", 
7145           av[CONTAINER_ROWID]);
7146   attr_array[0] = "distinguishedName";
7147   attr_array[1] = NULL;
7148   group_count = 0;
7149   group_base = NULL;
7150
7151   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
7152                            &group_base, &group_count, 
7153                            LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7154     {
7155       if (group_count == 1)
7156         {
7157           strcpy(distinguishedName, group_base->value);
7158         }
7159
7160       linklist_free(group_base);
7161       group_base = NULL;
7162       group_count = 0;
7163     }
7164
7165   if (strlen(distinguishedName) == 0)
7166     {
7167       sprintf(filter, "(&(objectClass=organizationalUnit)"
7168               "(distinguishedName=%s,%s))", dName, dn_path);
7169       attr_array[0] = "distinguishedName";
7170       attr_array[1] = NULL;
7171       group_count = 0;
7172       group_base = NULL;
7173
7174       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
7175                                &group_base, &group_count, 
7176                                LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7177         {
7178           if (group_count == 1)
7179             {
7180               strcpy(distinguishedName, group_base->value);
7181             }
7182
7183           linklist_free(group_base);
7184           group_base = NULL;
7185           group_count = 0;
7186         }
7187     }
7188
7189   return(0);
7190 }
7191
7192 int container_adupdate(LDAP *ldap_handle, char *dn_path, char *dName, 
7193                        char *distinguishedName, int count, char **av)
7194 {
7195   char      *attr_array[5];
7196   LK_ENTRY  *group_base;
7197   LK_ENTRY  *pPtr;
7198   LDAPMod   *mods[20];
7199   int       group_count;
7200   char      filter[512];
7201   char      *moiraId_v[] = {NULL, NULL};
7202   char      *desc_v[] = {NULL, NULL};
7203   char      *managedBy_v[] = {NULL, NULL};
7204   char      managedByDN[256];
7205   char      moiraId[64];
7206   char      desc[256];
7207   char      ad_path[512];
7208   int       rc;
7209   int       i;
7210   int       n;
7211
7212
7213   strcpy(ad_path, distinguishedName);
7214
7215   if (strlen(dName) != 0)
7216     sprintf(ad_path, "%s,%s", dName, dn_path);
7217
7218   sprintf(filter, "(&(objectClass=organizationalUnit)(distinguishedName=%s))",
7219           ad_path);
7220
7221   if (strlen(av[CONTAINER_ID]) != 0)
7222     sprintf(filter, "(&(objectClass=organizationalUnit)(mitMoiraId=%s))", 
7223             av[CONTAINER_ROWID]);
7224
7225   attr_array[0] = "mitMoiraId";
7226   attr_array[1] = "description";
7227   attr_array[2] = "managedBy";
7228   attr_array[3] = NULL;
7229   group_count = 0;
7230   group_base = NULL;
7231
7232   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
7233                            &group_base, &group_count, 
7234                            LDAP_SCOPE_SUBTREE)) != LDAP_SUCCESS)
7235     {
7236       com_err(whoami, 0, "Unable to retreive container info for %s : %s",
7237               av[CONTAINER_NAME], ldap_err2string(rc));
7238       return(rc);
7239     }
7240
7241   memset(managedByDN, '\0', sizeof(managedByDN));
7242   memset(moiraId, '\0', sizeof(moiraId));
7243   memset(desc, '\0', sizeof(desc));
7244   pPtr = group_base;
7245
7246   while (pPtr)
7247     {
7248       if (!strcasecmp(pPtr->attribute, "description"))
7249         strcpy(desc, pPtr->value);
7250       else if (!strcasecmp(pPtr->attribute, "managedBy"))
7251         strcpy(managedByDN, pPtr->value);
7252       else if (!strcasecmp(pPtr->attribute, "mitMoiraId"))
7253         strcpy(moiraId, pPtr->value);
7254       pPtr = pPtr->next;
7255     }
7256
7257   linklist_free(group_base);
7258   group_base = NULL;
7259   group_count = 0;
7260
7261   n = 0;
7262   if (strlen(av[CONTAINER_ROWID]) != 0)
7263     {
7264       moiraId_v[0] = av[CONTAINER_ROWID];
7265       ADD_ATTR("mitMoiraId", moiraId_v, LDAP_MOD_REPLACE);
7266     }
7267
7268   if (strlen(av[CONTAINER_DESC]) != 0)
7269     {
7270       attribute_update(ldap_handle, ad_path, av[CONTAINER_DESC], "description",
7271                        dName);
7272     }
7273   else
7274     {
7275       if (strlen(desc) != 0)
7276         {
7277           attribute_update(ldap_handle, ad_path, "", "description", dName);
7278         }
7279     }
7280
7281   if ((strlen(av[CONTAINER_TYPE]) != 0) && (strlen(av[CONTAINER_ID]) != 0))
7282     {
7283       if (!strcasecmp(av[CONTAINER_TYPE], "KERBEROS"))
7284         {
7285           if (!contact_create(ldap_handle, dn_path, av[CONTAINER_ID], 
7286                               kerberos_ou))
7287             {
7288               sprintf(managedByDN, "CN=%s,%s,%s", av[CONTAINER_ID], 
7289                       kerberos_ou, dn_path);
7290               managedBy_v[0] = managedByDN;
7291               ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_REPLACE);
7292             }
7293           else
7294             {
7295               if (strlen(managedByDN) != 0)
7296                 {
7297                   attribute_update(ldap_handle, ad_path, "", "managedBy", 
7298                                    dName);
7299                 }
7300             }
7301         }
7302       else
7303         {
7304           memset(filter, '\0', sizeof(filter));
7305
7306           if (!strcasecmp(av[CONTAINER_TYPE], "USER"))
7307             {
7308               sprintf(filter, "(&(cn=%s)(&(objectCategory=person)"
7309                       "(objectClass=user)))", av[CONTAINER_ID]);
7310             }
7311
7312           if (!strcasecmp(av[CONTAINER_TYPE], "LIST"))
7313             {
7314               sprintf(filter, "(&(objectClass=group)(cn=%s))", 
7315                       av[CONTAINER_ID]);
7316             }
7317
7318           if (strlen(filter) != 0)
7319             {
7320               attr_array[0] = "distinguishedName";
7321               attr_array[1] = NULL;
7322               group_count = 0;
7323               group_base = NULL;
7324               if ((rc = linklist_build(ldap_handle, dn_path, filter, 
7325                                        attr_array, &group_base, &group_count, 
7326                                        LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7327                 {
7328                   if (group_count == 1)
7329                     {
7330                       strcpy(managedByDN, group_base->value);
7331                       managedBy_v[0] = managedByDN;
7332                       ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_REPLACE);
7333                     }
7334                   else
7335                     {
7336                       if (strlen(managedByDN) != 0)
7337                         {
7338                           attribute_update(ldap_handle, ad_path, "", 
7339                                            "managedBy", dName);
7340                         }
7341                     }
7342
7343                   linklist_free(group_base);
7344                   group_base = NULL;
7345                   group_count = 0;
7346                 }
7347             }
7348           else
7349             {
7350               if (strlen(managedByDN) != 0)
7351                 {
7352                   attribute_update(ldap_handle, ad_path, "", "managedBy", 
7353                                    dName);
7354                 }
7355             }
7356         }
7357     }
7358
7359   mods[n] = NULL;
7360
7361   if (n == 0)
7362     return(LDAP_SUCCESS);
7363
7364   rc = ldap_modify_s(ldap_handle, ad_path, mods);
7365
7366   for (i = 0; i < n; i++)
7367     free(mods[i]);
7368
7369   if (rc != LDAP_SUCCESS)
7370     {
7371       com_err(whoami, 0, "Unable to modify container info for %s : %s",
7372               av[CONTAINER_NAME], ldap_err2string(rc));
7373       return(rc);
7374     }
7375   
7376   return(rc);
7377 }
7378
7379 int container_move_objects(LDAP *ldap_handle, char *dn_path, char *dName)
7380 {
7381   char      *attr_array[3];
7382   LK_ENTRY  *group_base;
7383   LK_ENTRY  *pPtr;
7384   int       group_count;
7385   char      filter[512];
7386   char      new_cn[128];
7387   char      temp[256];
7388   int       rc;
7389   int       NumberOfEntries = 10;
7390   int       i;
7391   int       count;
7392
7393   rc = ldap_set_option(ldap_handle, LDAP_OPT_SIZELIMIT, &NumberOfEntries);
7394
7395   for (i = 0; i < 3; i++)
7396     {
7397       memset(filter, '\0', sizeof(filter));
7398
7399       if (i == 0)
7400         {
7401           strcpy(filter, "(!(|(objectClass=computer)"
7402                  "(objectClass=organizationalUnit)))");
7403           attr_array[0] = "cn";
7404           attr_array[1] = NULL;
7405         }
7406       else if (i == 1)
7407         {
7408           strcpy(filter, "(objectClass=computer)");
7409           attr_array[0] = "cn";
7410           attr_array[1] = NULL;
7411         }
7412       else
7413         {
7414           strcpy(filter, "(objectClass=organizationalUnit)");
7415           attr_array[0] = "ou";
7416           attr_array[1] = NULL;
7417         }
7418
7419       while (1)
7420         {
7421           if ((rc = linklist_build(ldap_handle, dName, filter, attr_array, 
7422                                    &group_base, &group_count, 
7423                                    LDAP_SCOPE_SUBTREE)) != LDAP_SUCCESS)
7424             {
7425               break;
7426             }
7427
7428           if (group_count == 0)
7429             break;
7430
7431           pPtr = group_base;
7432
7433           while(pPtr)
7434             {
7435               if (!strcasecmp(pPtr->attribute, "cn"))
7436                 {
7437                   sprintf(new_cn, "cn=%s", pPtr->value);
7438                   if (i == 0)
7439                     sprintf(temp, "%s,%s", orphans_other_ou, dn_path);
7440                   if (i == 1)
7441                     sprintf(temp, "%s,%s", orphans_machines_ou, dn_path);
7442                   count = 1;
7443
7444                   while (1)
7445                     {
7446                       rc = ldap_rename_s(ldap_handle, pPtr->dn, new_cn, temp,
7447                                          TRUE, NULL, NULL);
7448                       if (rc == LDAP_ALREADY_EXISTS)
7449                         {
7450                           sprintf(new_cn, "cn=%s_%d", pPtr->value, count);
7451                           ++count;
7452                         }
7453                       else
7454                         break;
7455                     }
7456                 }
7457               else if (!strcasecmp(pPtr->attribute, "ou"))
7458                 {
7459                   rc = ldap_delete_s(ldap_handle, pPtr->dn);
7460                 }
7461
7462               pPtr = pPtr->next;
7463             }
7464
7465           linklist_free(group_base);
7466           group_base = NULL;
7467           group_count = 0;
7468         }
7469     }
7470
7471   return(0);
7472 }
7473
7474 int get_machine_ou(LDAP *ldap_handle, char *dn_path, char *member, 
7475                    char *machine_ou, char *NewMachineName)
7476 {
7477   LK_ENTRY  *group_base;
7478   int  group_count;
7479   int  i;
7480   char filter[128];
7481   char *attr_array[3];
7482   char cn[256];
7483   char dn[256];
7484   char temp[256];
7485   char *pPtr;
7486   int   rc;
7487
7488   strcpy(NewMachineName, member);
7489   rc = moira_connect();
7490   rc = GetMachineName(NewMachineName);
7491   moira_disconnect();
7492
7493   if (strlen(NewMachineName) == 0)
7494     {
7495       com_err(whoami, 0, "Unable to find alais for machine %s in Moira", 
7496               member);
7497       return(1);
7498     }
7499
7500   pPtr = NULL;
7501   pPtr = strchr(NewMachineName, '.');
7502
7503   if (pPtr != NULL)
7504     (*pPtr) = '\0';
7505
7506   group_base = NULL;
7507   group_count = 0;
7508   sprintf(filter, "(sAMAccountName=%s$)", NewMachineName);
7509   attr_array[0] = "cn";
7510   attr_array[1] = NULL;
7511   sprintf(temp, "%s", dn_path);
7512
7513   if ((rc = linklist_build(ldap_handle, temp, filter, attr_array, 
7514                            &group_base, &group_count, 
7515                            LDAP_SCOPE_SUBTREE)) != 0)
7516     {
7517       com_err(whoami, 0, "Unable to process machine %s : %s",
7518               member, ldap_err2string(rc));
7519       return(1);
7520     }
7521
7522   if (group_count != 1)
7523     {
7524       return(1);
7525     }
7526
7527   strcpy(dn, group_base->dn);
7528   strcpy(cn, group_base->value);
7529
7530   for (i = 0; i < (int)strlen(dn); i++)
7531     dn[i] = tolower(dn[i]);
7532
7533   for (i = 0; i < (int)strlen(cn); i++)
7534     cn[i] = tolower(cn[i]);
7535
7536   linklist_free(group_base);
7537   pPtr = NULL;
7538   pPtr = strstr(dn, cn);
7539
7540   if (pPtr == NULL)
7541     {
7542       com_err(whoami, 0, "Unable to process machine %s",
7543               member);
7544       return(1);
7545     }
7546
7547   pPtr += strlen(cn) + 1;
7548   strcpy(machine_ou, pPtr);
7549   pPtr = NULL;
7550   pPtr = strstr(machine_ou, "dc=");
7551
7552   if (pPtr == NULL)
7553     {
7554       com_err(whoami, 0, "Unable to process machine %s",
7555               member);
7556       return(1);
7557     }
7558
7559   --pPtr;
7560   (*pPtr) = '\0';
7561
7562   return(0);
7563 }
7564
7565 int machine_move_to_ou(LDAP *ldap_handle, char * dn_path, 
7566                        char *MoiraMachineName, char *DestinationOu)
7567 {
7568   char        NewCn[128];
7569   char        OldDn[512];
7570   char        MachineName[128];
7571   char        filter[128];
7572   char        *attr_array[3];
7573   char        NewOu[256];
7574   char        *cPtr = NULL;
7575   int         group_count;
7576   long        rc;
7577   LK_ENTRY    *group_base;
7578
7579   group_count = 0;
7580   group_base = NULL;
7581   
7582   strcpy(MachineName, MoiraMachineName);
7583   rc = GetMachineName(MachineName);
7584
7585   if (strlen(MachineName) == 0)
7586     {
7587       com_err(whoami, 0, "Unable to find alais for machine %s in Moira", 
7588               MoiraMachineName);
7589       return(1);
7590     }
7591   
7592   cPtr = strchr(MachineName, '.');
7593
7594   if (cPtr != NULL)
7595     (*cPtr) = '\0';
7596
7597   sprintf(filter, "(sAMAccountName=%s$)", MachineName);
7598   attr_array[0] = "sAMAccountName";
7599   attr_array[1] = NULL;
7600
7601   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
7602                            &group_base, 
7603                            &group_count, LDAP_SCOPE_SUBTREE)) != 0)
7604     {
7605       com_err(whoami, 0, "Unable to process machine %s : %s",
7606               MoiraMachineName, ldap_err2string(rc));
7607       return(1);
7608     }
7609   
7610   if (group_count == 1)
7611     strcpy(OldDn, group_base->dn);
7612
7613   linklist_free(group_base);
7614   group_base = NULL;
7615
7616   if (group_count != 1)
7617     {
7618       com_err(whoami, 0, "Unable to find machine %s in directory: %s", 
7619               MoiraMachineName);
7620       return(1);
7621     }
7622
7623   sprintf(NewOu, "%s,%s", DestinationOu, dn_path);
7624   cPtr = strchr(OldDn, ',');
7625
7626   if (cPtr != NULL)
7627     {
7628       ++cPtr;
7629       if (!strcasecmp(cPtr, NewOu))
7630         return(0);
7631     }
7632
7633   sprintf(NewCn, "CN=%s", MachineName);
7634   rc = ldap_rename_s(ldap_handle, OldDn, NewCn, NewOu, TRUE, NULL, NULL);
7635
7636   return(rc);
7637 }
7638
7639 int machine_check(LDAP *ldap_handle, char *dn_path, char *machine_name)
7640 {
7641   char    Name[128];
7642   char    *pPtr;
7643   int     rc;
7644   
7645   memset(Name, '\0', sizeof(Name));
7646   strcpy(Name, machine_name);
7647   pPtr = NULL;
7648   pPtr = strchr(Name, '.');
7649
7650   if (pPtr != NULL)
7651     (*pPtr) = '\0';
7652
7653   strcat(Name, "$");
7654   return(!(rc = checkADname(ldap_handle, dn_path, Name)));
7655 }
7656
7657 int machine_get_moira_container(LDAP *ldap_handle, char *dn_path, 
7658                                 char *machine_name, char *container_name)
7659 {
7660   int     rc;
7661   char    *av[2];
7662   char    *call_args[2];
7663   
7664   av[0] = machine_name;
7665   call_args[0] = (char *)container_name;
7666   rc = mr_query("get_machine_to_container_map", 1, av, 
7667                 machine_GetMoiraContainer, call_args);
7668   return(rc);
7669 }
7670
7671 int machine_GetMoiraContainer(int ac, char **av, void *ptr)
7672 {
7673   char **call_args;
7674   
7675   call_args = ptr;
7676   strcpy(call_args[0], av[1]);
7677   return(0);
7678 }
7679
7680 int Moira_container_group_create(char **after)
7681 {
7682   long rc;
7683   char GroupName[64];
7684   char *argv[20];
7685   
7686   memset(GroupName, '\0', sizeof(GroupName));
7687   rc = Moira_groupname_create(GroupName, after[CONTAINER_NAME], 
7688                               after[CONTAINER_ROWID]);
7689   if (rc)
7690     return rc;
7691   
7692   argv[L_NAME] = GroupName;
7693   argv[L_ACTIVE] = "1";
7694   argv[L_PUBLIC] = "0";
7695   argv[L_HIDDEN] = "0";
7696   argv[L_MAILLIST] = "0";
7697   argv[L_GROUP] = "1";
7698   argv[L_GID] = UNIQUE_GID;
7699   argv[L_NFSGROUP] = "0";
7700   argv[L_MAILMAN] = "0";
7701   argv[L_MAILMAN_SERVER] = "[NONE]";
7702   argv[L_DESC] = "auto created container group";
7703   argv[L_ACE_TYPE] = "USER";
7704   argv[L_MEMACE_TYPE] = "USER";
7705   argv[L_ACE_NAME] = "sms";
7706   argv[L_MEMACE_NAME] = "sms";
7707
7708   if (rc = mr_query("add_list", 15, argv, NULL, NULL))
7709     {
7710       com_err(whoami, 0, 
7711               "Unable to create container group %s for container %s: %s",
7712               GroupName, after[CONTAINER_NAME], error_message(rc));
7713     }
7714
7715   Moira_setContainerGroup(after[CONTAINER_NAME], GroupName);
7716   Moira_addGroupToParent(after[CONTAINER_NAME], GroupName);
7717   
7718   return(rc);
7719 }
7720
7721 int Moira_container_group_update(char **before, char **after)
7722 {
7723   long rc;
7724   char BeforeGroupName[64];
7725   char AfterGroupName[64];
7726   char *argv[20];
7727   
7728   if (!strcasecmp(after[CONTAINER_NAME], before[CONTAINER_NAME]))
7729     return(0);
7730
7731   memset(BeforeGroupName, '\0', sizeof(BeforeGroupName));
7732   Moira_getGroupName(after[CONTAINER_NAME], BeforeGroupName, 0);
7733   if (strlen(BeforeGroupName) == 0)
7734     return(0);
7735
7736   memset(AfterGroupName, '\0', sizeof(AfterGroupName));
7737   rc = Moira_groupname_create(AfterGroupName, after[CONTAINER_NAME], 
7738                               after[CONTAINER_ROWID]);
7739   if (rc)
7740     return rc;
7741
7742   if (strcasecmp(BeforeGroupName, AfterGroupName))
7743     {
7744       argv[L_NAME] = BeforeGroupName;
7745       argv[L_NAME + 1] = AfterGroupName;
7746       argv[L_ACTIVE + 1] = "1";
7747       argv[L_PUBLIC + 1] = "0";
7748       argv[L_HIDDEN + 1] = "0";
7749       argv[L_MAILLIST + 1] = "0";
7750       argv[L_GROUP + 1] = "1";
7751       argv[L_GID + 1] = UNIQUE_GID;
7752       argv[L_NFSGROUP + 1] = "0";
7753       argv[L_MAILMAN + 1] = "0";
7754       argv[L_MAILMAN_SERVER + 1] = "[NONE]";
7755       argv[L_DESC + 1] = "auto created container group";
7756       argv[L_ACE_TYPE + 1] = "USER";
7757       argv[L_MEMACE_TYPE + 1] = "USER";
7758       argv[L_ACE_NAME + 1] = "sms";
7759       argv[L_MEMACE_NAME + 1] = "sms";
7760       
7761       if (rc = mr_query("update_list", 16, argv, NULL, NULL))
7762         {
7763           com_err(whoami, 0, 
7764                   "Unable to rename container group from %s to %s: %s",
7765                   BeforeGroupName, AfterGroupName, error_message(rc));
7766         }
7767     }
7768   
7769   return(rc);
7770 }
7771
7772 int Moira_container_group_delete(char **before)
7773 {
7774   long rc = 0;
7775   char *argv[13];
7776   char GroupName[64];
7777   char ParentGroupName[64];
7778   
7779   memset(ParentGroupName, '\0', sizeof(ParentGroupName));
7780   Moira_getGroupName(before[CONTAINER_NAME], ParentGroupName, 1);
7781
7782   memset(GroupName, '\0', sizeof(GroupName));
7783
7784   if (strcmp(before[CONTAINER_GROUP_NAME], "[none]"))
7785     strcpy(GroupName, before[CONTAINER_GROUP_NAME]);
7786   
7787   if ((strlen(ParentGroupName) != 0) && (strlen(GroupName) != 0))
7788     {
7789       argv[0] = ParentGroupName;
7790       argv[1] = "LIST";
7791       argv[2] = GroupName;
7792
7793       if (rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL))
7794         {
7795           com_err(whoami, 0, 
7796                   "Unable to delete container group %s from list: %s",
7797                   GroupName, ParentGroupName, error_message(rc));
7798         }
7799     }
7800   
7801   if (strlen(GroupName) != 0)
7802     {
7803       argv[0] = GroupName;
7804
7805       if (rc = mr_query("delete_list", 1, argv, NULL, NULL))
7806         {
7807           com_err(whoami, 0, "Unable to delete container group %s : %s",
7808                   GroupName, error_message(rc));
7809         }
7810     }
7811   
7812   return(rc);
7813 }
7814
7815 int Moira_groupname_create(char *GroupName, char *ContainerName,
7816                            char *ContainerRowID)
7817 {
7818   char *ptr;
7819   char *ptr1;
7820   char temp[64];
7821   char newGroupName[64];
7822   char tempGroupName[64];
7823   char tempgname[64];
7824   char *argv[1];
7825   int  i;
7826   long rc;
7827
7828   strcpy(temp, ContainerName);
7829   
7830   ptr1 = strrchr(temp, '/');
7831
7832   if (ptr1 != NULL)
7833   {
7834     *ptr1 = '\0';
7835     ptr = ++ptr1;
7836     ptr1 = strrchr(temp, '/');
7837
7838     if (ptr1 != NULL)
7839     {
7840         sprintf(tempgname, "%s-%s", ++ptr1, ptr);
7841     }
7842     else
7843         strcpy(tempgname, ptr);
7844   }
7845   else
7846     strcpy(tempgname, temp);
7847
7848   if (strlen(tempgname) > 25)
7849     tempgname[25] ='\0';
7850
7851   sprintf(newGroupName, "cnt-%s", tempgname);
7852
7853   /* change everything to lower case */
7854   ptr = newGroupName;
7855
7856   while (*ptr)
7857     {
7858       if (isupper(*ptr))
7859         *ptr = tolower(*ptr);
7860
7861       if (*ptr == ' ')
7862         *ptr = '-';
7863
7864       ptr++;
7865     }
7866
7867   strcpy(tempGroupName, newGroupName);
7868   i = (int)'0';
7869
7870   /* append 0-9 then a-z if a duplicate is found */
7871   while(1)
7872     {
7873       argv[0] = newGroupName;
7874
7875       if (rc = mr_query("get_list_info", 1, argv, NULL, NULL))
7876         {
7877           if (rc == MR_NO_MATCH)
7878             break;
7879           com_err(whoami, 0, "Moira error while creating group name for "
7880                   "container %s : %s", ContainerName, error_message(rc));
7881           return rc;
7882         }
7883
7884       sprintf(newGroupName, "%s-%c", tempGroupName, i);
7885
7886       if (i == (int)'z')
7887         {
7888           com_err(whoami, 0, "Unable to find a unique group name for "
7889                   "container %s: too many duplicate container names",
7890                   ContainerName);
7891           return 1;
7892         }
7893
7894       if (i == '9')
7895         i = 'a';
7896       else
7897         i++;
7898     }
7899
7900   strcpy(GroupName, newGroupName);
7901   return(0);
7902 }
7903
7904 int Moira_setContainerGroup(char *origContainerName, char *GroupName)
7905 {
7906   long rc;
7907   char *argv[3];
7908   
7909   argv[0] = origContainerName;
7910   argv[1] = GroupName;
7911   
7912   if ((rc = mr_query("set_container_list", 2, argv, NULL, NULL)))
7913     {
7914       com_err(whoami, 0, 
7915               "Unable to set container group %s in container %s: %s",
7916               GroupName, origContainerName, error_message(rc));
7917     }
7918   
7919   return(0);
7920 }
7921
7922 int Moira_addGroupToParent(char *origContainerName, char *GroupName)
7923  {
7924    char ContainerName[64];
7925    char ParentGroupName[64];
7926    char *argv[3];
7927    long rc;
7928
7929    strcpy(ContainerName, origContainerName);
7930    
7931    Moira_getGroupName(ContainerName, ParentGroupName, 1);
7932
7933    /* top-level container */
7934    if (strlen(ParentGroupName) == 0)
7935      return(0);
7936    
7937    argv[0] = ParentGroupName;
7938    argv[1] = "LIST";
7939    argv[2] = GroupName;
7940
7941    if ((rc = mr_query("add_member_to_list", 3, argv, NULL, NULL)))
7942      {
7943        com_err(whoami, 0, 
7944                "Unable to add container group %s to parent group %s: %s",
7945                GroupName, ParentGroupName, error_message(rc));
7946      }
7947    
7948    return(0);
7949  }
7950
7951 int Moira_getContainerGroup(int ac, char **av, void *ptr)
7952 {
7953   char **call_args;
7954   
7955   call_args = ptr;
7956   strcpy(call_args[0], av[1]);
7957
7958   return(0);
7959 }
7960
7961 int Moira_getGroupName(char *origContainerName, char *GroupName,
7962                        int ParentFlag)
7963 {
7964   char ContainerName[64];
7965   char *argv[3];
7966   char *call_args[3];
7967   char *ptr;
7968   long rc;
7969
7970   strcpy(ContainerName, origContainerName);
7971
7972   if (ParentFlag)
7973     {
7974       ptr = strrchr(ContainerName, '/');
7975
7976       if (ptr != NULL)
7977         (*ptr) = '\0';
7978       else
7979         return(0);
7980     }
7981
7982   argv[0] = ContainerName;
7983   argv[1] = NULL;
7984   call_args[0] = GroupName;
7985   call_args[1] = NULL;
7986
7987   if (!(rc = mr_query("get_container_list", 1, argv, Moira_getContainerGroup,
7988                       call_args)))
7989     {
7990       if (strlen(GroupName) != 0)
7991         return(0);
7992     }
7993
7994   if (rc)
7995     com_err(whoami, 0, "Unable to get container group from container %s: %s",
7996             ContainerName, error_message(rc));
7997   else
7998     com_err(whoami, 0, "Unable to get container group from container %s",
7999             ContainerName);
8000   
8001   return(0);
8002 }
8003
8004 int Moira_process_machine_container_group(char *MachineName, char* GroupName, 
8005                                           int DeleteMachine)
8006 {
8007   char *argv[3];
8008   long rc;
8009   
8010   if (strcmp(GroupName, "[none]") == 0)
8011     return 0;
8012
8013   argv[0] = GroupName;
8014   argv[1] = "MACHINE";
8015   argv[2] = MachineName;
8016
8017   if (!DeleteMachine)
8018     rc = mr_query("add_member_to_list", 3, argv, NULL, NULL);
8019   else
8020     rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL);
8021
8022   if (rc)
8023     {
8024       com_err(whoami, 0, "Unable to add machine %s to container group%s: %s",
8025               MachineName, GroupName, error_message(rc));
8026     }
8027
8028   return(0);
8029 }
8030
8031 int GetMachineName(char *MachineName)
8032 {
8033   char    *args[2];
8034   char    NewMachineName[1024];
8035   char    *szDot;
8036   int     rc = 0;
8037   int     i;
8038   DWORD   dwLen = 0;
8039   char    *call_args[2];
8040   
8041   // If the address happens to be in the top-level MIT domain, great!
8042   strcpy(NewMachineName, MachineName);
8043
8044   for (i = 0; i < (int)strlen(NewMachineName); i++)
8045     NewMachineName[i] = toupper(NewMachineName[i]);
8046
8047   szDot = strchr(NewMachineName,'.');
8048
8049   if ((szDot) && (!strcasecmp(szDot+1, DOMAIN_SUFFIX)))
8050     {
8051       return(0);
8052     }
8053   
8054   // If not, see if it has a Moira alias in the top-level MIT domain.
8055   memset(NewMachineName, '\0', sizeof(NewMachineName));
8056   args[0] = "*";
8057   args[1] = MachineName;
8058   call_args[0] = NewMachineName;
8059   call_args[1] = NULL;
8060
8061   if (rc = mr_query("get_hostalias", 2, args, ProcessMachineName, call_args))
8062     {
8063       com_err(whoami, 0, "Unable to resolve machine name %s : %s",
8064               MachineName, error_message(rc));
8065       strcpy(MachineName, "");
8066       return(0);
8067     }
8068   
8069   if (strlen(NewMachineName) != 0)
8070     strcpy(MachineName, NewMachineName);
8071   else
8072     strcpy(MachineName, "");
8073
8074   return(0);
8075 }
8076
8077 int ProcessMachineName(int ac, char **av, void *ptr)
8078 {
8079   char    **call_args;
8080   char    MachineName[1024];
8081   char    *szDot;
8082   int     i;
8083   
8084   call_args = ptr;
8085
8086   if (strlen(call_args[0]) == 0)
8087     {
8088       strcpy(MachineName, av[0]);
8089
8090       for (i = 0; i < (int)strlen(MachineName); i++)
8091         MachineName[i] = toupper(MachineName[i]);
8092
8093       szDot = strchr(MachineName,'.');
8094
8095         if ((szDot) && (!strcasecmp(szDot+1,DOMAIN_SUFFIX)))
8096           {
8097             strcpy(call_args[0], MachineName);
8098           }
8099     }
8100
8101   return(0);
8102 }
8103
8104 void SwitchSFU(LDAPMod **mods, int *UseSFU30, int n)
8105 {
8106   int i;
8107   
8108   if (*UseSFU30)
8109     {
8110       for (i = 0; i < n; i++)
8111         {
8112           if (!strcmp(mods[i]->mod_type, "msSFU30UidNumber"))
8113             mods[i]->mod_type = "uidNumber";
8114         }
8115
8116       (*UseSFU30) = 0;
8117     }
8118   else
8119     {
8120       for (i = 0; i < n; i++)
8121         {
8122           if (!strcmp(mods[i]->mod_type, "uidNumber"))
8123             mods[i]->mod_type = "msSFU30UidNumber";
8124         }
8125
8126       (*UseSFU30) = 1;
8127     }
8128 }
8129
8130 int SetHomeDirectory(LDAP *ldap_handle, char *user_name, 
8131                      char *DistinguishedName,
8132                      char *WinHomeDir, char *WinProfileDir,
8133                      char **homedir_v, char **winProfile_v,
8134                      char **drives_v, LDAPMod **mods, 
8135                      int OpType, int n)
8136 {
8137   char cWeight[3];
8138   char cPath[1024];
8139   char path[1024];
8140   char winPath[1024];
8141   char winProfile[1024];
8142   char homeDrive[8];
8143   char homedir[1024];
8144   char apple_homedir[1024];
8145   char *apple_homedir_v[] = {NULL, NULL};
8146   int  last_weight;
8147   int  i;
8148   int  rc;
8149   LDAPMod *DelMods[20];
8150   char *argv[3];
8151   char *save_argv[FS_END];
8152   char *fsgroup_save_argv[2];
8153
8154   memset(homeDrive, '\0', sizeof(homeDrive));
8155   memset(path, '\0', sizeof(path));
8156   memset(winPath, '\0', sizeof(winPath));
8157   memset(winProfile, '\0', sizeof(winProfile));
8158
8159   if(!ActiveDirectory) 
8160     {
8161       if (rc = moira_connect())
8162         {
8163           critical_alert("Ldap incremental",
8164                          "Error contacting Moira server : %s",
8165                          error_message(rc));
8166           return;
8167         }
8168       
8169       argv[0] = user_name;
8170
8171       if (!(rc = mr_query("get_filesys_by_label", 1, argv, save_query_info, 
8172                           save_argv)))
8173         {
8174           if(!strcmp(save_argv[FS_TYPE], "FSGROUP") ||
8175              !strcmp(save_argv[FS_TYPE], "MUL"))
8176             {
8177         
8178               argv[0] = save_argv[FS_NAME];
8179               fsgCount = 0;
8180               
8181               if (!(rc = mr_query("get_fsgroup_members", 1, argv, 
8182                                   save_fsgroup_info, fsgroup_save_argv)))
8183                 {
8184                   if(fsgCount)
8185                     {
8186                       argv[0] = fsgroup_save_argv[0];
8187                       
8188                       if (!(rc = mr_query("get_filesys_by_label", 1, argv, 
8189                                           save_query_info, save_argv)))
8190                         {
8191                           strcpy(path, save_argv[FS_PACK]);
8192                         }
8193                     }
8194                 }
8195             }
8196           else
8197             {
8198               strcpy(path, save_argv[FS_PACK]);
8199             }
8200         }
8201       
8202       moira_disconnect();
8203
8204       if (strlen(path))
8205         {
8206           if (!strnicmp(path, AFS, strlen(AFS)))
8207             {
8208               sprintf(homedir, "%s", path);
8209               sprintf(apple_homedir, "%s/MacData", path);
8210               homedir_v[0] = homedir;
8211               apple_homedir_v[0] = apple_homedir;
8212               ADD_ATTR("homeDirectory", homedir_v, OpType);
8213               ADD_ATTR("apple-user-homeDirectory", apple_homedir_v, 
8214                        OpType);
8215             }
8216         }
8217       else
8218         {
8219           homedir_v[0] = "NONE";
8220           apple_homedir_v[0] = "NONE";
8221           ADD_ATTR("homeDirectory", homedir_v, OpType);
8222           ADD_ATTR("apple-user-homeDirectory", apple_homedir_v, 
8223                    OpType);
8224         }
8225
8226       return(n);
8227     }
8228  
8229   if ((!strcasecmp(WinHomeDir, "[afs]")) || 
8230       (!strcasecmp(WinProfileDir, "[afs]")))
8231     {
8232       if (rc = moira_connect())
8233         {
8234           critical_alert("Ldap incremental",
8235                          "Error contacting Moira server : %s",
8236                          error_message(rc));
8237           return;
8238         }
8239       
8240       argv[0] = user_name;
8241
8242       if (!(rc = mr_query("get_filesys_by_label", 1, argv, save_query_info, 
8243                           save_argv)))
8244         {
8245           if(!strcmp(save_argv[FS_TYPE], "FSGROUP") ||
8246              !strcmp(save_argv[FS_TYPE], "MUL"))
8247             {
8248         
8249               argv[0] = save_argv[FS_NAME];
8250               fsgCount = 0;
8251               
8252               if (!(rc = mr_query("get_fsgroup_members", 1, argv, 
8253                                   save_fsgroup_info, fsgroup_save_argv)))
8254                 {
8255                   if(fsgCount)
8256                     {
8257                       argv[0] = fsgroup_save_argv[0];
8258                       
8259                       if (!(rc = mr_query("get_filesys_by_label", 1, argv, 
8260                                           save_query_info, save_argv)))
8261                         {
8262                           strcpy(path, save_argv[FS_PACK]);
8263                         }
8264                     }
8265                 }
8266             }
8267           else
8268             {
8269               strcpy(path, save_argv[FS_PACK]);
8270             }
8271         }
8272      
8273       moira_disconnect();
8274
8275       if (strlen(path))
8276         {
8277           if (!strnicmp(path, AFS, strlen(AFS)))
8278             {
8279               AfsToWinAfs(path, winPath);
8280               strcpy(winProfile, winPath);
8281               strcat(winProfile, "\\.winprofile");
8282             }
8283         }
8284       else
8285         return(n);
8286     }
8287
8288     if ((!strcasecmp(WinHomeDir, "[dfs]")) || 
8289         (!strcasecmp(WinProfileDir, "[dfs]")))
8290     {
8291       sprintf(path, "\\\\%s\\dfs\\profiles\\%c\\%s", ldap_domain, 
8292               user_name[0], user_name);
8293
8294       if (!strcasecmp(WinProfileDir, "[dfs]"))
8295         {
8296           strcpy(winProfile, path);
8297           strcat(winProfile, "\\.winprofile");
8298         }
8299
8300       if (!strcasecmp(WinHomeDir, "[dfs]"))
8301         strcpy(winPath, path);
8302     }
8303     
8304     if (!strcasecmp(WinHomeDir, "[local]"))
8305       memset(winPath, '\0', sizeof(winPath));
8306     else if (!strcasecmp(WinHomeDir, "[afs]") || 
8307              !strcasecmp(WinHomeDir, "[dfs]"))
8308       {
8309         strcpy(homeDrive, "H:");
8310       }
8311     else
8312       {
8313         strcpy(winPath, WinHomeDir);
8314         if (!strncmp(WinHomeDir, "\\\\", 2))
8315           {
8316             strcpy(homeDrive, "H:");
8317           }        
8318       }
8319     
8320     // nothing needs to be done if WinProfileDir is [afs].
8321     if (!strcasecmp(WinProfileDir, "[local]"))
8322       memset(winProfile, '\0', sizeof(winProfile));
8323     else if (strcasecmp(WinProfileDir, "[afs]") && 
8324              strcasecmp(WinProfileDir, "[dfs]"))
8325       {
8326         strcpy(winProfile, WinProfileDir);
8327       }
8328     
8329     if (strlen(winProfile) != 0)
8330       {
8331         if (winProfile[strlen(winProfile) - 1] == '\\')
8332           winProfile[strlen(winProfile) - 1] = '\0';
8333       }
8334
8335     if (strlen(winPath) != 0)
8336       {
8337         if (winPath[strlen(winPath) - 1] == '\\')
8338           winPath[strlen(winPath) - 1] = '\0';
8339       }
8340     
8341     if ((winProfile[1] == ':') && (strlen(winProfile) == 2))
8342       strcat(winProfile, "\\");
8343
8344     if ((winPath[1] == ':') && (strlen(winPath) == 2))
8345       strcat(winPath, "\\");
8346     
8347     if (strlen(winPath) == 0)
8348       {
8349         if (OpType == LDAP_MOD_REPLACE)
8350           {
8351             i = 0;
8352             DEL_ATTR("homeDirectory", LDAP_MOD_DELETE);
8353             DelMods[i] = NULL;
8354             //unset homeDirectory attribute for user.
8355             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
8356             free(DelMods[0]);
8357           }
8358       }
8359     else
8360       {
8361         homedir_v[0] = strdup(winPath);
8362         ADD_ATTR("homeDirectory", homedir_v, OpType);
8363       }
8364     
8365     if (strlen(winProfile) == 0)
8366       {
8367         if (OpType == LDAP_MOD_REPLACE)
8368           {
8369             i = 0;
8370             DEL_ATTR("profilePath", LDAP_MOD_DELETE);
8371             DelMods[i] = NULL;
8372             //unset profilePate attribute for user.
8373             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
8374             free(DelMods[0]);
8375           }
8376       }
8377     else
8378       {
8379         winProfile_v[0] = strdup(winProfile);
8380         ADD_ATTR("profilePath", winProfile_v, OpType);
8381       }
8382     
8383     if (strlen(homeDrive) == 0)
8384       {
8385         if (OpType == LDAP_MOD_REPLACE)
8386           {
8387             i = 0;
8388             DEL_ATTR("homeDrive", LDAP_MOD_DELETE);
8389             DelMods[i] = NULL;
8390             //unset homeDrive attribute for user
8391             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
8392             free(DelMods[0]);
8393           }
8394       }
8395     else
8396       {
8397         drives_v[0] = strdup(homeDrive);
8398         ADD_ATTR("homeDrive", drives_v, OpType);
8399       }
8400
8401     return(n);
8402 }
8403
8404 int attribute_update(LDAP *ldap_handle, char *distinguished_name, 
8405                      char *attribute_value, char *attribute, char *user_name)
8406 {
8407   char      *mod_v[] = {NULL, NULL};
8408   LDAPMod   *DelMods[20];
8409   LDAPMod   *mods[20];
8410   int       n;
8411   int       i;
8412   int       rc;
8413   
8414   if (strlen(attribute_value) == 0)
8415     {
8416       i = 0;
8417       DEL_ATTR(attribute, LDAP_MOD_DELETE);
8418       DelMods[i] = NULL;
8419       rc = ldap_modify_s(ldap_handle, distinguished_name, DelMods);
8420       free(DelMods[0]);
8421     }
8422   else
8423     {
8424       n = 0;
8425       mod_v[0] = attribute_value;
8426       ADD_ATTR(attribute, mod_v, LDAP_MOD_REPLACE);
8427       mods[n] = NULL;
8428
8429       if ((rc = ldap_modify_s(ldap_handle, distinguished_name, 
8430                               mods)) != LDAP_SUCCESS)
8431         {
8432           free(mods[0]);
8433           n = 0;
8434           mod_v[0] = attribute_value;
8435           ADD_ATTR(attribute, mod_v, LDAP_MOD_ADD);
8436           mods[n] = NULL;
8437
8438           if ((rc = ldap_modify_s(ldap_handle, distinguished_name, 
8439                                   mods)) != LDAP_SUCCESS)
8440             {
8441               com_err(whoami, 0, "Unable to change the %s attribute for %s "
8442                       "in the directory : %s",
8443                       attribute, user_name, ldap_err2string(rc));
8444             }
8445         }
8446
8447       free(mods[0]);
8448     }
8449   
8450   return(rc);
8451 }
8452
8453 void StringTrim(char *StringToTrim)
8454 {
8455   char *t, *s;
8456   char *save;
8457
8458   save = strdup(StringToTrim);
8459
8460   s = save;
8461
8462   while (isspace(*s))
8463     s++;
8464
8465   /* skip to end of string */
8466   if (*s == '\0')
8467     {
8468       if (*save)
8469         *save = '\0';
8470       strcpy(StringToTrim, save);
8471       return;
8472     }
8473   
8474   for (t = s; *t; t++)
8475     continue;
8476
8477   while (t > s)
8478     {
8479       --t;
8480       if (!isspace(*t))
8481         {
8482           t++;
8483           break;
8484         }
8485     }
8486
8487   if (*t)
8488     *t = '\0';
8489   
8490   strcpy(StringToTrim, s);
8491   return;
8492 }
8493
8494 int ReadConfigFile(char *DomainName)
8495 {
8496     int     Count;
8497     int     i;
8498     int     k;
8499     char    temp[256];
8500     char    temp1[256];
8501     FILE    *fptr;
8502
8503     Count = 0;
8504
8505     sprintf(temp, "%s%s.cfg", CFG_PATH, DomainName);
8506
8507     if ((fptr = fopen(temp, "r")) != NULL)
8508       {
8509         while (fgets(temp, sizeof(temp), fptr) != 0)
8510           {
8511             for (i = 0; i < (int)strlen(temp); i++)
8512               temp[i] = toupper(temp[i]);
8513
8514             if (temp[strlen(temp) - 1] == '\n')
8515               temp[strlen(temp) - 1] = '\0';
8516
8517             StringTrim(temp);
8518
8519             if (strlen(temp) == 0)
8520               continue;
8521
8522             if (!strncmp(temp, DOMAIN, strlen(DOMAIN)))
8523               {
8524                 if (strlen(temp) > (strlen(DOMAIN)))
8525                   {
8526                     strcpy(ldap_domain, &temp[strlen(DOMAIN)]);
8527                     StringTrim(ldap_domain);
8528                   }
8529               }
8530             else if (!strncmp(temp, REALM, strlen(REALM)))
8531               {
8532                 if (strlen(temp) > (strlen(REALM)))
8533                   {
8534                     strcpy(ldap_realm, &temp[strlen(REALM)]);
8535                     StringTrim(ldap_realm);
8536                   }
8537               }
8538             else if (!strncmp(temp, PORT, strlen(PORT)))
8539               {
8540                 if (strlen(temp) > (strlen(PORT)))
8541                   {
8542                     strcpy(ldap_port, &temp[strlen(PORT)]);
8543                     StringTrim(ldap_port);
8544                   }
8545               }
8546             else if (!strncmp(temp, PRINCIPALNAME, strlen(PRINCIPALNAME)))
8547               {
8548                 if (strlen(temp) > (strlen(PRINCIPALNAME)))
8549                   {
8550                     strcpy(PrincipalName, &temp[strlen(PRINCIPALNAME)]);
8551                     StringTrim(PrincipalName);
8552                   }
8553               }
8554             else if (!strncmp(temp, SERVER, strlen(SERVER)))
8555               {
8556                 if (strlen(temp) > (strlen(SERVER)))
8557                   {
8558                     ServerList[Count] = calloc(1, 256);
8559                     strcpy(ServerList[Count], &temp[strlen(SERVER)]);
8560                     StringTrim(ServerList[Count]);
8561                     ++Count;
8562                   }
8563               }
8564             else if (!strncmp(temp, MSSFU, strlen(MSSFU)))
8565               {
8566                 if (strlen(temp) > (strlen(MSSFU)))
8567                   {
8568                     strcpy(temp1, &temp[strlen(MSSFU)]);
8569                     StringTrim(temp1);
8570                     if (!strcmp(temp1, SFUTYPE))
8571                       UseSFU30 = 1;
8572                   }
8573               }
8574             else if (!strncmp(temp, GROUP_SUFFIX, strlen(GROUP_SUFFIX)))
8575               {
8576                 if (strlen(temp) > (strlen(GROUP_SUFFIX)))
8577                   {
8578                     strcpy(temp1, &temp[strlen(GROUP_SUFFIX)]);
8579                     StringTrim(temp1);
8580                     if (!strcasecmp(temp1, "NO")) 
8581                       {
8582                         UseGroupSuffix = 0;
8583                         memset(group_suffix, '\0', sizeof(group_suffix));
8584                       }
8585                   }
8586               }
8587             else if (!strncmp(temp, GROUP_TYPE, strlen(GROUP_TYPE)))
8588               {
8589                 if (strlen(temp) > (strlen(GROUP_TYPE)))
8590                   {
8591                     strcpy(temp1, &temp[strlen(GROUP_TYPE)]);
8592                     StringTrim(temp1);
8593                     if (!strcasecmp(temp1, "UNIVERSAL")) 
8594                       UseGroupUniversal = 1;
8595                   }
8596               }
8597             else if (!strncmp(temp, SET_GROUP_ACE, strlen(SET_GROUP_ACE)))
8598               {
8599                 if (strlen(temp) > (strlen(SET_GROUP_ACE)))
8600                   {
8601                     strcpy(temp1, &temp[strlen(SET_GROUP_ACE)]);
8602                     StringTrim(temp1);
8603                     if (!strcasecmp(temp1, "NO"))
8604                       SetGroupAce = 0;
8605                   }
8606               }
8607             else if (!strncmp(temp, SET_PASSWORD, strlen(SET_PASSWORD)))
8608               {
8609                 if (strlen(temp) > (strlen(SET_PASSWORD)))
8610                   {
8611                     strcpy(temp1, &temp[strlen(SET_PASSWORD)]);
8612                     StringTrim(temp1);
8613                     if (!strcasecmp(temp1, "NO"))
8614                       SetPassword = 0;
8615                   }
8616               }
8617             else if (!strncmp(temp, EXCHANGE, strlen(EXCHANGE)))
8618               {
8619                 if (strlen(temp) > (strlen(EXCHANGE)))
8620                   {
8621                     strcpy(temp1, &temp[strlen(EXCHANGE)]);
8622                     StringTrim(temp1);
8623                     if (!strcasecmp(temp1, "YES"))
8624                       Exchange = 1;
8625                   }
8626               }
8627             else if (!strncmp(temp, PROCESS_MACHINE_CONTAINER, 
8628                               strlen(PROCESS_MACHINE_CONTAINER)))
8629               {
8630                 if (strlen(temp) > (strlen(PROCESS_MACHINE_CONTAINER)))
8631                   {
8632                     strcpy(temp1, &temp[strlen(PROCESS_MACHINE_CONTAINER)]);
8633                     StringTrim(temp1);
8634                     if (!strcasecmp(temp1, "NO"))
8635                       ProcessMachineContainer = 0;
8636                   }
8637               }
8638             else if (!strncmp(temp, ACTIVE_DIRECTORY, 
8639                               strlen(ACTIVE_DIRECTORY)))
8640               {
8641                 if (strlen(temp) > (strlen(ACTIVE_DIRECTORY)))
8642                   {
8643                     strcpy(temp1, &temp[strlen(ACTIVE_DIRECTORY)]);
8644                     StringTrim(temp1);
8645                     if (!strcasecmp(temp1, "NO"))
8646                       ActiveDirectory = 0;
8647                   }
8648               }
8649             else if (!strncmp(temp, GROUP_POPULATE_MEMBERS, 
8650                               strlen(GROUP_POPULATE_MEMBERS)))
8651               {
8652                 if (strlen(temp) > (strlen(GROUP_POPULATE_MEMBERS)))
8653                   {
8654                     strcpy(temp1, &temp[strlen(GROUP_POPULATE_MEMBERS)]);
8655                     StringTrim(temp1);
8656                     if (!strcasecmp(temp1, "DELETE")) 
8657                       {
8658                         GroupPopulateDelete = 1;
8659                       }
8660                   }
8661               }
8662             else
8663               {
8664                 if (strlen(ldap_domain) != 0)
8665                   {
8666                     memset(ldap_domain, '\0', sizeof(ldap_domain));
8667                     break;
8668                   }
8669
8670                 if (strlen(temp) != 0)
8671                   strcpy(ldap_domain, temp);
8672               }
8673           }
8674         fclose(fptr);
8675       }
8676     
8677     if (strlen(ldap_domain) == 0)
8678       {
8679       strcpy(ldap_domain, DomainName);
8680       }
8681
8682     if (Count == 0)
8683         return(0);
8684
8685     for (i = 0; i < Count; i++)
8686       {
8687         if (ServerList[i] != 0)
8688           {
8689             for (k = 0; k < (int)strlen(ServerList[i]); k++)
8690               ServerList[i][k] = toupper(ServerList[i][k]);
8691           }
8692       }
8693     
8694     return(0);
8695 }
8696
8697 int ReadDomainList()
8698 {
8699   int     Count;
8700   int     i;
8701   char    temp[128];
8702   char    temp1[128];
8703   FILE    *fptr;
8704   unsigned char c[11];
8705   unsigned char stuff[256];
8706   int     rc;
8707   int     ok;
8708
8709   Count = 0;
8710   sprintf(temp, "%s%s", CFG_PATH, WINADCFG);
8711
8712   if ((fptr = fopen(temp, "r")) != NULL)
8713     {
8714       while (fgets(temp, sizeof(temp), fptr) != 0)
8715         {
8716           for (i = 0; i < (int)strlen(temp); i++)
8717             temp[i] = toupper(temp[i]);
8718
8719           if (temp[strlen(temp) - 1] == '\n')
8720             temp[strlen(temp) - 1] = '\0';
8721
8722           StringTrim(temp);
8723
8724           if (strlen(temp) == 0)
8725             continue;
8726
8727           if (!strncmp(temp, DOMAIN, strlen(DOMAIN)))
8728             {
8729               if (strlen(temp) > (strlen(DOMAIN)))
8730                 {
8731                   strcpy(temp1, &temp[strlen(DOMAIN)]);
8732                   StringTrim(temp1);
8733                   strcpy(temp, temp1);
8734                 }
8735             }
8736           
8737           strcpy(DomainNames[Count], temp);
8738           StringTrim(DomainNames[Count]);
8739           ++Count;
8740         }
8741
8742       fclose(fptr);
8743     }
8744
8745   if (Count == 0)
8746     {
8747       critical_alert("incremental", "%s", "ldap.incr cannot run due to a "
8748                      "configuration error in ldap.cfg");
8749       return(1);
8750     }
8751   
8752   return(0);
8753 }
8754
8755 int email_isvalid(const char *address) {
8756   int        count = 0;
8757   const char *c, *domain;
8758   static char *rfc822_specials = "()<>@,;:\\\"[]";
8759
8760   if(address[strlen(address) - 1] == '.') 
8761     return 0;
8762     
8763   /* first we validate the name portion (name@domain) */
8764   for (c = address;  *c;  c++) {
8765     if (*c == '\"' && (c == address || *(c - 1) == '.' || *(c - 1) == 
8766                        '\"')) {
8767       while (*++c) {
8768         if (*c == '\"') 
8769           break;
8770         if (*c == '\\' && (*++c == ' ')) 
8771           continue;
8772         if (*c <= ' ' || *c >= 127) 
8773           return 0;
8774       }
8775
8776       if (!*c++) 
8777         return 0;
8778       if (*c == '@') 
8779         break;
8780       if (*c != '.') 
8781         return 0;
8782       continue;
8783     }
8784
8785     if (*c == '@') 
8786       break;
8787     if (*c <= ' ' || *c >= 127) 
8788       return 0;
8789     if (strchr(rfc822_specials, *c)) 
8790       return 0;
8791   }
8792
8793   if (c == address || *(c - 1) == '.') 
8794     return 0;
8795
8796   /* next we validate the domain portion (name@domain) */
8797   if (!*(domain = ++c)) return 0;
8798   do {
8799     if (*c == '.') {
8800       if (c == domain || *(c - 1) == '.') 
8801         return 0;
8802       count++;
8803     }
8804     if (*c <= ' ' || *c >= 127) 
8805       return 0;
8806     if (strchr(rfc822_specials, *c)) 
8807       return 0;
8808   } while (*++c);
8809
8810   return (count >= 1);
8811 }
8812
8813 int find_homeMDB(LDAP *ldap_handle, char *dn_path, char **homeMDB, 
8814              char **homeServerName) 
8815 {
8816   LK_ENTRY *group_base;
8817   LK_ENTRY *sub_group_base;
8818   LK_ENTRY *gPtr;
8819   LK_ENTRY *sub_gPtr;
8820   int      group_count;
8821   int      sub_group_count;
8822   char     filter[1024];
8823   char     sub_filter[1024];
8824   char     search_path[1024];
8825   char     range[1024];
8826   char     *attr_array[3];
8827   char     *s;
8828   int      homeMDB_count = -1;
8829   int      rc;
8830   int      i;
8831   int      mdbbl_count;
8832   int      rangeStep = 1500;
8833   int      rangeLow = 0;
8834   int      rangeHigh = rangeLow + (rangeStep - 1);
8835   int      isLast = 0;
8836
8837   /* Grumble..... microsoft not making it searchable from the root *grr* */
8838
8839   memset(filter, '\0', sizeof(filter));
8840   memset(search_path, '\0', sizeof(search_path));
8841   
8842   sprintf(filter, "(objectClass=msExchMDB)");
8843   sprintf(search_path, "CN=Configuration,%s", dn_path);
8844   attr_array[0] = "distinguishedName";
8845   attr_array[1] = NULL;
8846   
8847   group_base = NULL;
8848   group_count = 0;
8849   
8850   if ((rc = linklist_build(ldap_handle, search_path, filter, attr_array,
8851                            &group_base, &group_count, 
8852                            LDAP_SCOPE_SUBTREE)) != 0) 
8853     {
8854       com_err(whoami, 0, "Unable to find msExchMDB %s",
8855               ldap_err2string(rc));
8856       return(rc);
8857     }
8858   
8859   if (group_count) 
8860     {
8861       gPtr = group_base;
8862       
8863       while(gPtr) {
8864         if (((s = strstr(gPtr->dn, "Public")) != (char *) NULL) ||
8865             ((s = strstr(gPtr->dn, "Recover")) != (char *) NULL) || 
8866             ((s = strstr(gPtr->dn, "Reserve")) != (char *) NULL))
8867           {
8868             gPtr = gPtr->next;
8869             continue;
8870           }
8871
8872         /* 
8873          * Due to limits in active directory we need to use the LDAP
8874          * range semantics to query and return all the values in 
8875          * large lists, we will stop increasing the range when
8876          * the result count is 0.
8877          */
8878
8879         i = 0;  
8880         mdbbl_count = 0;
8881
8882         for(;;) 
8883           {
8884             memset(sub_filter, '\0', sizeof(sub_filter));
8885             memset(range, '\0', sizeof(range));
8886             sprintf(sub_filter, "(objectClass=msExchMDB)");
8887
8888             if(isLast)
8889               sprintf(range, "homeMDBBL;Range=%d-*", rangeLow);
8890             else 
8891               sprintf(range, "homeMDBBL;Range=%d-%d", rangeLow, rangeHigh);
8892
8893             attr_array[0] = range;
8894             attr_array[1] = NULL;
8895             
8896             sub_group_base = NULL;
8897             sub_group_count = 0;
8898             
8899             if ((rc = linklist_build(ldap_handle, gPtr->dn, sub_filter, 
8900                                      attr_array, &sub_group_base, 
8901                                      &sub_group_count, 
8902                                      LDAP_SCOPE_SUBTREE)) != 0) 
8903               {
8904                 com_err(whoami, 0, "Unable to find homeMDBBL %s",
8905                         ldap_err2string(rc));
8906                 return(rc);
8907               }
8908
8909             if(!sub_group_count)
8910               {
8911                 if(isLast) 
8912                   {
8913                     isLast = 0;
8914                     rangeLow = 0;
8915                     rangeHigh = rangeLow + (rangeStep - 1);
8916                     break;
8917                   }
8918                 else
8919                   isLast++;
8920               }
8921
8922             mdbbl_count += sub_group_count;
8923             rangeLow = rangeHigh + 1;
8924             rangeHigh = rangeLow + (rangeStep - 1);
8925           }
8926
8927         /* First time through, need to initialize or update the least used */
8928         
8929         com_err(whoami, 0, "Mail store %s, count %d", gPtr->dn, 
8930                 mdbbl_count);
8931
8932         if(mdbbl_count < homeMDB_count || homeMDB_count == -1) 
8933           {
8934             homeMDB_count = mdbbl_count; 
8935             *homeMDB = strdup(gPtr->dn);
8936           }
8937
8938         gPtr = gPtr->next;
8939         linklist_free(sub_group_base);
8940       }
8941     }
8942
8943   linklist_free(group_base);
8944   
8945   /* 
8946    * Ok found the server least allocated need to now query to get its
8947    * msExchHomeServerName so we can set it as a user attribute
8948    */
8949   
8950   attr_array[0] = "legacyExchangeDN";
8951   attr_array[1] = NULL; 
8952   
8953   group_count = 0;
8954   group_base = NULL;
8955   
8956   if ((rc = linklist_build(ldap_handle, *homeMDB, filter, 
8957                            attr_array, &group_base, 
8958                            &group_count, 
8959                            LDAP_SCOPE_SUBTREE)) != 0) 
8960     {
8961       com_err(whoami, 0, "Unable to find msExchHomeServerName %s",
8962               ldap_err2string(rc));
8963       return(rc);
8964     }  
8965   
8966   if(group_count) 
8967     {
8968       *homeServerName = strdup(group_base->value);
8969       if((s = strrchr(*homeServerName, '/')) != (char *) NULL) 
8970         {
8971           *s = '\0';
8972         }
8973     } 
8974
8975   linklist_free(group_base);
8976   
8977   return(rc);
8978 }
8979       
8980 char *lowercase(char *s)
8981 {
8982   char *p;
8983
8984   for (p = s; *p; p++)
8985     {
8986       if (isupper(*p))
8987         *p = tolower(*p);
8988     }
8989   return s;
8990 }
8991
8992 char *uppercase(char *s)
8993 {
8994   char *p;
8995
8996   for (p = s; *p; p++)
8997     {
8998       if (islower(*p))
8999         *p = toupper(*p);
9000     }
9001   return s;
9002 }
9003
9004 char *escape_string(char *s)
9005 {
9006   char *p, *q;
9007   char string[1024];
9008   char temp[1024];
9009   int i = 0;
9010   int spaces = 0;
9011
9012   memset(string, '\0', sizeof(string));
9013
9014   q = s;
9015
9016   /* Escape any special characters */
9017
9018   for(; *q != '\0'; q++) {
9019     if(*q == ',')
9020       string[i++] = '\\';
9021     if(*q == '+') 
9022       string[i++] = '\\';
9023     if(*q == '"') 
9024       string[i++] = '\\';
9025     if(*q == '\\') 
9026       string[i++] = '\\';
9027     if(*q == '<') 
9028       string[i++] = '\\';
9029     if(*q == '>') 
9030       string[i++] = '\\';
9031     if(*q == ';')
9032       string[i++] = '\\';
9033     if(*q == '#')
9034       string[i++] = '\\';
9035     if(*q == '=')
9036       string[i++] = '\\';
9037
9038     string[i++] = *q;
9039   }
9040
9041   return strdup(string);
9042 }
9043
9044 int save_query_info(int argc, char **argv, void *hint)
9045 {
9046   int i;
9047   char **nargv = hint;
9048
9049   for(i = 0; i < argc; i++)
9050     nargv[i] = strdup(argv[i]);
9051
9052   return MR_CONT;
9053 }
9054
9055 int save_fsgroup_info(int argc, char **argv, void *hint)
9056 {
9057   int i;
9058   char **nargv = hint;
9059
9060   if(!fsgCount) 
9061     {
9062       for(i = 0; i < argc; i++)
9063         nargv[i] = strdup(argv[i]);
9064
9065       fsgCount++;
9066     }
9067
9068   return MR_CONT;
9069 }
This page took 0.782926 seconds and 5 git commands to generate.