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