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