]> andersk Git - moira.git/blob - incremental/winad/winad.c
Support EXCHANGE poboxes.
[moira.git] / incremental / winad / winad.c
1 /* $Header$
2 /* winad.incr arguments examples
3  *
4  * arguments when moira creates the account - ignored by winad.incr since the account is unusable.
5  * users 0 11 #45198 45198 /bin/cmd cmd Last First Middle 0 950000001 2000 121049
6  *   login, unix_uid, shell, winconsoleshell, last, first, middle, status, mitid, type, moiraid
7  *
8  * arguments for creating or updating a user account 
9  * users 11 11 username 45206 /bin/cmd cmd Last First Middle 2 950000001 STAFF 121058  PathToHomeDir PathToProfileDir username 45206 /bin/cmd cmd Last First Middle 1 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
10  * users 11 11 #45206 45206 /bin/cmd cmd Last First Middle 0 950000001 STAFF 121058  PathToHomeDir PathToProfileDir newuser 45206 /bin/cmd cmd Last First Middle 2 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
11  *   login, unix_uid, shell, winconsoleshell, last, first, middle, status, mitid, type, moiraid
12  *
13  * arguments for deactivating/deleting a user account
14  * users 11 11 username 45206 /bin/cmd cmd Last First Middle 1 950000001 STAFF 121058  PathToHomeDir PathToProfileDir username 45206 /bin/cmd cmd Last First Middle 3 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
15  * users 11 11 username 45206 /bin/cmd cmd Last First Middle 2 950000001 STAFF 121058  PathToHomeDir PathToProfileDir username 45206 /bin/cmd cmd Last First Middle 3 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
16  *   login, unix_uid, shell, winconsoleshell, last, first, middle, status, mitid, type, moiraid
17  *
18  * arguments for reactivating a user account
19  * users 11 11 username 45206 /bin/cmd cmd Last First Middle 3 950000001 STAFF 121058 username 45206 /bin/cmd cmd Last First Middle 1 950000001 STAFF 121058
20  * users 11 11 username 45206 /bin/cmd cmd Last First Middle 3 950000001 STAFF 121058 username 45206 /bin/cmd cmd Last First Middle 2 950000001 STAFF 121058
21  *   login, unix_uid, shell, winconsoleshell, last, first, middle, status, mitid, type, moiraid
22  *
23  * arguments for changing user name
24  * users 11 11 oldusername 45206 /bin/cmd cmd Last First Middle 1 950000001 STAFF 121058 PathToHomeDir PathToProfileDir newusername 45206 /bin/cmd cmd Last First Middle 1 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
25  *   login, unix_uid, shell, winconsoleshell, last, first, middle, status, mitid, type, moiraid
26  *
27  * arguments for expunging a user
28  * users 11 0 username 45198 /bin/cmd cmd Last First Middle 0 950000001 2000 121049
29  *   login, unix_uid, shell, winconsoleshell, last, first, middle, status, mitid, type, moiraid
30  *
31  * arguments for creating a "special" group/list
32  * list 0 11 listname 1 1 0 0 0 -1 NONE 0 description 92616
33  *   listname, active, publicflg, hidden, maillist, grouplist, gid, acl_type, acl_id, description, moiraid
34  * 
35  * arguments for creating a "mail" group/list
36  * list 0 11 listname 1 1 0 1 0 -1 NONE 0 description 92616
37  *   listname, active, publicflg, hidden, maillist, grouplist, gid, acl_type, acl_id, description, moiraid
38  *
39  * arguments for creating a "group" group/list
40  * list 0 11 listname 1 1 0 0 1 -1 NONE 0 description 92616
41  *   listname, active, publicflg, hidden, maillist, grouplist, gid, acl_type, acl_id, description, moiraid
42  *
43  * arguments for creating a "group/mail" group/list
44  * list 0 11 listname 1 1 0 1 1 -1 NONE 0 description 92616
45  *   listname, active, publicflg, hidden, maillist, grouplist, gid, acl_type, acl_id, description, moiraid
46  *
47  * arguments to add a USER member to group/list
48  * imembers 0 12 listname USER userName 1 1 0 0 0 -1 1 92616 121047
49  *   list_name, user_type, name, active, publicflg, hidden, maillist, grouplist, gid, userStatus, moiraListId, moiraUserId
50  *
51  * arguments to add a STRING or KERBEROS member to group/list
52  * imembers 0 10 listname STRING stringName 1 1 0 0 0 -1 92616
53  * imembers 0 10 listlistnameName KERBEROS kerberosName 1 1 0 0 0 -1 92616
54  *   list_name, user_type, name, active, publicflg, hidden, maillist, grouplist, gid, moiraListId
55  *
56  * NOTE: group members of type LIST are ignored.
57  *
58  * arguments to remove a USER member to group/list
59  * imembers 12 0 listname USER userName 1 1 0 0 0 -1 1 92616 121047
60  *   list_name, user_type, name, active, publicflg, hidden, maillist, grouplist, gid, userStatus, moiraListId, moiraUserId
61  *
62  * arguments to remove a STRING or KERBEROS member to group/list
63  * imembers 10 0 listname STRING stringName 1 1 0 0 0 -1 92616
64  * imembers 10 0 listname KERBEROS kerberosName 1 1 0 0 0 -1 92616
65  *   list_name, user_type, name, active, publicflg, hidden, maillist, grouplist, gid, moiraListId
66  *
67  * NOTE: group members of type LIST are ignored.
68  *
69  * arguments for renaming a group/list
70  * list 11 11 oldlistname 1 1 0 0 0 -1 NONE 0 description 92616 newlistname 1 1 0 0 0 -1 description 0 92616
71  *   name, active, publicflg, hidden, maillist, grouplist, gid, acl_type, acl_id, description, moiraListId
72  *
73  * arguments for deleting a group/list
74  * list 11 0 listname 1 1 0 0 0 -1 NONE 0 description 92616
75  *   name, active, publicflg, hidden, maillist, grouplist, gid, acl_type, acl_id, description, moiraListId
76  *
77  * arguments for adding a file system
78  * filesys 0 12 username AFS ATHENA.MIT.EDU /afs/athena.mit.edu/user/n/e/username /mit/username w descripton username wheel 1 HOMEDIR 101727
79  *
80  * arguments for deleting a file system
81  * filesys 12 0 username AFS ATHENA.MIT.EDU /afs/athena.mit.edu/user/n/e/username /mit/username w descripton username wheel 1 HOMEDIR 101727
82  *
83  * arguments when moira creates a container (OU).
84  * containers 0 8 machines/test/bottom description location contact USER 105316 2222 [none]
85  *
86  * arguments when moira deletes a container (OU).
87  * containers 8 0 machines/test/bottom description location contact USER 105316 2222 groupname
88  *
89  * arguments when moira modifies a container information (OU).
90  * containers 8 8 machines/test/bottom description location contact USER 105316 2222 groupname machines/test/bottom description1 location contact USER 105316 2222 groupname
91  *
92  * arguments when moira adds a machine from an OU
93  * table name, beforec, afterc, machine_name, container_name, mach_id, cnt_id
94  * mcntmap 0 5 DAVIDT.MIT.EDU dttest/dttest1 76767 46 groupname
95  *
96  * arguments when moira removes a machine from an OU
97  * table name, beforec, afterc, machine_name, container_name, mach_id, cnt_id
98  * mcntmap 0 5 DAVIDT.MIT.EDU dttest/dttest1 76767 46 groupname
99  *
100 */
101 #include <mit-copyright.h>
102 #ifdef _WIN32
103 #include <winsock2.h>
104 #include <windows.h>
105 #include <stdlib.h>
106 #include <malloc.h>
107 #include <lmaccess.h>
108 #endif
109 #include <hesiod.h>
110 #include <string.h>
111 #include <ldap.h>
112 #include <stdio.h>
113 #include <moira.h>
114 #include <moira_site.h>
115 #include <mrclient.h>
116 #include <krb5.h>
117 #include <gsssasl.h>
118 #include <gssldap.h>
119 #include "kpasswd.h"
120
121 #ifdef _WIN32
122 #ifndef ECONNABORTED
123 #define ECONNABORTED WSAECONNABORTED
124 #endif
125 #ifndef ECONNREFUSED
126 #define ECONNREFUSED WSAECONNREFUSED
127 #endif
128 #ifndef EHOSTUNREACH
129 #define EHOSTUNREACH WSAEHOSTUNREACH
130 #endif
131 #define krb5_xfree free
132 #define F_OK 0
133 #define sleep(A) Sleep(A * 1000);
134 #endif /* _WIN32 */
135
136 #ifndef _WIN32
137 #include <sys/types.h>
138 #include <netinet/in.h>
139 #include <arpa/nameser.h>
140 #include <resolv.h>
141 #include <sys/utsname.h>
142 #include <unistd.h>
143
144 #define CFG_PATH "/moira/winad/"
145 #define WINADCFG "winad.cfg"
146 #define strnicmp(A,B,C) strncasecmp(A,B,C)
147 #define UCHAR unsigned char
148
149 #define UF_SCRIPT               0x0001
150 #define UF_ACCOUNTDISABLE       0x0002
151 #define UF_HOMEDIR_REQUIRED     0x0008
152 #define UF_LOCKOUT              0x0010
153 #define UF_PASSWD_NOTREQD       0x0020
154 #define UF_PASSWD_CANT_CHANGE   0x0040
155 #define UF_DONT_EXPIRE_PASSWD   0x10000
156
157 #define UF_TEMP_DUPLICATE_ACCOUNT       0x0100
158 #define UF_NORMAL_ACCOUNT               0x0200
159 #define UF_INTERDOMAIN_TRUST_ACCOUNT    0x0800
160 #define UF_WORKSTATION_TRUST_ACCOUNT    0x1000
161 #define UF_SERVER_TRUST_ACCOUNT         0x2000
162
163 #define OWNER_SECURITY_INFORMATION       (0x00000001L)
164 #define GROUP_SECURITY_INFORMATION       (0x00000002L)
165 #define DACL_SECURITY_INFORMATION        (0x00000004L)
166 #define SACL_SECURITY_INFORMATION        (0x00000008L)
167
168 #ifndef BYTE
169 #define BYTE unsigned char
170 #endif
171 typedef unsigned int DWORD;
172 typedef unsigned long ULONG;
173
174 typedef struct _GUID
175 {
176   unsigned long Data1;
177   unsigned short Data2;
178   unsigned short Data3;
179   unsigned char Data4[8];
180 } GUID;
181
182 typedef struct _SID_IDENTIFIER_AUTHORITY { 
183   BYTE Value[6]; 
184 } SID_IDENTIFIER_AUTHORITY, *PSID_IDENTIFIER_AUTHORITY; 
185
186 typedef struct _SID {
187   BYTE  Revision;
188   BYTE  SubAuthorityCount;
189   SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
190   DWORD SubAuthority[512];
191 } SID;
192 #endif/*!WIN32*/
193
194 #ifndef WINADCFG
195 #define WINADCFG "winad.cfg"
196 #endif
197
198 #ifndef CFG_PATH
199 #define CFG_PATH ""
200 #endif 
201
202 #define AFS "/afs/"
203 #define WINAFS "\\\\afs\\all\\"
204
205 #define ADS_GROUP_TYPE_GLOBAL_GROUP         0x00000002
206 #define ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP   0x00000004
207 #define ADS_GROUP_TYPE_LOCAL_GROUP          0x00000004
208 #define ADS_GROUP_TYPE_UNIVERSAL_GROUP      0x00000008
209 #define ADS_GROUP_TYPE_SECURITY_ENABLED     0x80000000
210
211 #define QUERY_VERSION   -1
212 #define PRIMARY_REALM   "ATHENA.MIT.EDU"
213 #define PRIMARY_DOMAIN  "win.mit.edu"
214 #define PRODUCTION_PRINCIPAL "sms"
215 #define TEST_PRINCIPAL       "smstest"
216
217 #define SUBSTITUTE  1
218 #define REPLACE     2
219
220 #define USERS         0
221 #define GROUPS        1
222
223 #define MEMBER_ADD          1
224 #define MEMBER_REMOVE       2
225 #define MEMBER_CHANGE_NAME  3
226 #define MEMBER_ACTIVATE     4
227 #define MEMBER_DEACTIVATE   5
228 #define MEMBER_CREATE       6
229
230 #define MOIRA_ALL       0x0
231 #define MOIRA_USERS     0x1
232 #define MOIRA_KERBEROS  0x2
233 #define MOIRA_STRINGS   0x4
234 #define MOIRA_LISTS     0x8
235
236 #define CHECK_GROUPS    1
237 #define CLEANUP_GROUPS  2
238
239 #define AD_NO_GROUPS_FOUND        -1
240 #define AD_WRONG_GROUP_DN_FOUND   -2
241 #define AD_MULTIPLE_GROUPS_FOUND  -3
242 #define AD_INVALID_NAME           -4
243 #define AD_LDAP_FAILURE           -5
244 #define AD_INVALID_FILESYS        -6
245 #define AD_NO_ATTRIBUTE_FOUND     -7
246 #define AD_NO_OU_FOUND            -8
247 #define AD_NO_USER_FOUND          -9
248
249 /* container arguments */
250 #define CONTAINER_NAME       0
251 #define CONTAINER_DESC       1
252 #define CONTAINER_LOCATION   2
253 #define CONTAINER_CONTACT    3
254 #define CONTAINER_TYPE       4
255 #define CONTAINER_ID         5
256 #define CONTAINER_ROWID      6
257 #define CONTAINER_GROUP_NAME 7
258
259 /*mcntmap arguments*/
260 #define OU_MACHINE_NAME        0
261 #define OU_CONTAINER_NAME      1
262 #define OU_MACHINE_ID          2
263 #define OU_CONTAINER_ID        3
264 #define OU_CONTAINER_GROUP     4
265
266 typedef struct lk_entry {
267   int     op;
268   int     length;
269   int     ber_value;
270   char    *dn;
271   char    *attribute;
272   char    *value;
273   char    *member;
274   char    *type;
275   char    *list;
276   struct  lk_entry *next;
277 } LK_ENTRY;
278
279 #define STOP_FILE "/moira/winad/nowinad"
280 #define file_exists(file) (access((file), F_OK) == 0)
281
282 #define N_SD_BER_BYTES   5
283 #define LDAP_BERVAL struct berval
284 #define MAX_SERVER_NAMES 32
285
286 #define HIDDEN_GROUP                "HiddenGroup.g"
287 #define HIDDEN_GROUP_WITH_ADMIN     "HiddenGroupWithAdmin.g"
288 #define NOT_HIDDEN_GROUP            "NotHiddenGroup.g"
289 #define NOT_HIDDEN_GROUP_WITH_ADMIN "NotHiddenGroupWithAdmin.g"
290
291 #define ADD_ATTR(t, v, o)               \
292   mods[n] = malloc(sizeof(LDAPMod));    \
293   mods[n]->mod_op = o;  \
294   mods[n]->mod_type = t;                \
295   mods[n++]->mod_values = v
296
297 #define DEL_ATTR(t, o)          \
298   DelMods[i] = malloc(sizeof(LDAPMod)); \
299   DelMods[i]->mod_op = o;       \
300   DelMods[i]->mod_type = t;             \
301   DelMods[i++]->mod_values = NULL
302
303 #define DOMAIN_SUFFIX   "MIT.EDU"
304 #define DOMAIN  "DOMAIN:"
305 #define PRINCIPALNAME  "PRINCIPAL:"
306 #define SERVER  "SERVER:"
307 #define MSSFU   "SFU:"
308 #define SFUTYPE "30"
309 #define MAX_DOMAINS 10
310 char DomainNames[MAX_DOMAINS][128];
311
312 char    PrincipalName[128];
313 #ifndef _WIN32
314 #define KRB5CCNAME "KRB5CCNAME=/tmp/krb5cc_winad.incr"
315 #define KRBTKFILE "KRBTKFILE=/tmp/tkt_winad.incr"
316 #define KEYTABFILE "/etc/krb5.keytab"
317 #else
318 #define KRB5CCNAME "KRB5CCNAME=\\tmp\\krb5cc_winad.incr"
319 #define KRBTKFILE "KRBTKFILE=\\tmp\\tkt_winad.incr"
320 #define KEYTABFILE "\\keytabs\\krb5.keytab"
321 #endif
322
323 LK_ENTRY *member_base = NULL;
324 static char tbl_buf[1024];
325 char  kerberos_ou[] = "OU=kerberos,OU=moira";
326 char  contact_ou[] = "OU=strings,OU=moira";
327 char  user_ou[] = "OU=users,OU=moira";
328 char  group_ou_distribution[] = "OU=mail,OU=lists,OU=moira";
329 char  group_ou_root[] = "OU=lists,OU=moira";
330 char  group_ou_security[] = "OU=group,OU=lists,OU=moira";
331 char  group_ou_neither[] = "OU=special,OU=lists,OU=moira";
332 char  group_ou_both[] = "OU=mail,OU=group,OU=lists,OU=moira";
333 char  orphans_machines_ou[] = "OU=Machines,OU=Orphans";
334 char  orphans_other_ou[] = "OU=Other,OU=Orphans";
335 char  security_template_ou[] = "OU=security_templates";
336 char *whoami;
337 char ldap_domain[256];
338 char *ServerList[MAX_SERVER_NAMES];
339 int  mr_connections = 0;
340 int  callback_rc;
341 char default_server[256];
342 static char tbl_buf[1024];
343 int  UseSFU30 = 0;
344 int  NoChangeConfigFile;
345 int  UpdateDomainList;
346
347 extern int set_password(char *user, char *password, char *domain);
348
349 int ad_get_group(LDAP *ldap_handle, char *dn_path, char *group_name, 
350                 char *group_membership, char *MoiraId, char *attribute,
351                 LK_ENTRY **linklist_base, int *linklist_count,
352               char *rFilter);
353 void AfsToWinAfs(char* path, char* winPath);
354 int ad_connect(LDAP **ldap_handle, char *ldap_domain, char *dn_path, 
355                char *Win2kPassword, char *Win2kUser, char *default_server,
356                int connect_to_kdc, char **ServerList);
357 void ad_kdc_disconnect();
358 int ad_server_connect(char *connectedServer, char *domain);
359 int attribute_update(LDAP *ldap_handle, char *distinguished_name, 
360                       char *attribute_value, char *attribute, char *user_name);
361 int BEREncodeSecurityBits(ULONG uBits, char *pBuffer);
362 int checkADname(LDAP *ldap_handle, char *dn_path, char *Name);
363 int check_winad(void);
364 int check_user(LDAP *ldap_handle, char *dn_path, char *UserName, char *MoiraId);
365 /* containers */
366 int container_adupdate(LDAP *ldap_handle, char *dn_path, char *dName, 
367                        char *distinguishedName, int count, char **av);
368 void container_check(LDAP *ldap_handle, char *dn_path, char *name);
369 int container_create(LDAP *ldap_handle, char *dn_path, int count, char **av);
370 int container_delete(LDAP *ldap_handle, char *dn_path, int count, char **av);
371 int container_get_distinguishedName(LDAP *ldap_handle, char *dn_path, 
372                                      char *distinguishedName, int count, char **av);
373 void container_get_dn(char *src, char *dest);
374 void container_get_name(char *src, char *dest);
375 int container_move_objects(LDAP *ldap_handle, char *dn_path, char *dName);
376 int container_rename(LDAP *ldap_handle, char *dn_path, int beforec, char **before, 
377                      int afterc, char **after);
378 int container_update(LDAP *ldap_handle, char *dn_path, int beforec, char **before,
379                      int afterc, char **after);
380
381 int GetAceInfo(int ac, char **av, void *ptr);
382 int GetServerList(char *ldap_domain, char **MasterServe);
383 int get_group_membership(char *group_membership, char *group_ou, 
384                          int *security_flag, char **av);
385 int get_machine_ou(LDAP *ldap_handle, char *dn_path, char *member, char *machine_ou, char *pPtr);
386 int Moira_container_group_create(char **after);
387 int Moira_container_group_delete(char **before);
388 int Moira_groupname_create(char *GroupName, char *ContainerName,
389                            char *ContainerRowID);
390 int Moira_container_group_update(char **before, char **after);
391 int Moira_process_machine_container_group(char *MachineName, char* groupName,
392                                           int DeleteMachine);
393 int Moira_addGroupToParent(char *origContainerName, char *GroupName);
394 int Moira_getContainerGroup(int ac, char **av, void *ptr);
395 int Moira_getGroupName(char *origContainerName, char *GroupName,
396                        int ParentFlag);
397 int Moira_setContainerGroup(char *ContainerName, char *GroupName);
398 int ProcessAce(LDAP *ldap_handle, char *dn_path, char *group_name, char *Type,
399                int UpdateGroup, int *ProcessGroup);
400 int process_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
401                   char *group_name, char *group_ou, char *group_membership, 
402                   int group_security_flag, int type);
403 int process_lists(int ac, char **av, void *ptr);
404 int ProcessGroupSecurity(LDAP *ldap_handle, char *dn_path, char *TargetGroupName, 
405                          int HiddenGroup, char *AceType, char *AceName);
406 int ProcessMachineName(int ac, char **av, void *ptr);
407 int ReadConfigFile(char *DomainName);
408 int ReadDomainList();
409 void StringTrim(char *StringToTrim);
410 int user_create(int ac, char **av, void *ptr);
411 int user_change_status(LDAP *ldap_handle, char *dn_path, 
412                        char *user_name, char *MoiraId, int operation);
413 int user_delete(LDAP *ldap_handle, char *dn_path, 
414                 char *u_name, char *MoiraId);
415 int user_rename(LDAP *ldap_handle, char *dn_path, char *before_user_name, 
416                 char *user_name);
417 int user_update(LDAP *ldap_handle, char *dn_path, char *user_name,
418                 char *uid, char *MitId, char *MoiraId, int State,
419                 char *WinHomeDir, char *WinProfileDir);
420 void change_to_lower_case(char *ptr);
421 int contact_create(LDAP *ld, char *bind_path, char *user, char *group_ou);
422 int group_create(int ac, char **av, void *ptr);
423 int group_delete(LDAP *ldap_handle, char *dn_path, 
424                  char *group_name, char *group_membership, char *MoiraId);
425 int group_rename(LDAP *ldap_handle, char *dn_path, 
426                  char *before_group_name, char *before_group_membership, 
427                  char *before_group_ou, int before_security_flag, char *before_desc,
428                  char *after_group_name, char *after_group_membership, 
429                  char *after_group_ou, int after_security_flag, char *after_desc,
430                  char *MoiraId, char *filter);
431 int machine_check(LDAP *ldap_handle, char *dn_path, char *machine_name);
432 int machine_GetMoiraContainer(int ac, char **av, void *ptr);
433 int machine_get_moira_container(LDAP *ldap_handle, char *dn_path, char *machine_name, char *container_name);
434 int machine_move_to_ou(LDAP *ldap_handle, char *dn_path, char *MoiraMachineName, char *DestinationOu);
435 int make_new_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
436                    char *group_name, char *group_ou, char *group_membership, 
437                    int group_security_flag, int updateGroup);
438 int member_list_build(int ac, char **av, void *ptr);
439 int member_add(LDAP *ldap_handle, char *dn_path, char *group_name, 
440                         char *group_ou, char *group_membership, 
441                         char *user_name, char *pUserOu, char *MoiraId);
442 int member_remove(LDAP *ldap_handle, char *dn_path, char *group_name, 
443                   char *group_ou, char *group_membership, char *user_name,
444                   char *pUserOu, char *MoiraId);
445 int populate_group(LDAP *ldap_handle, char *dn_path, char *group_name, 
446                    char *group_ou, char *group_membership, 
447                    int group_security_flag, char *MoiraId);
448 int SetHomeDirectory(LDAP *ldap_handle, char *user_name, char *DistinguishedName,
449                      char *WinHomeDir, char *WinProfileDir,
450                      char **homedir_v, char **winProfile_v,
451                      char **drives_v, LDAPMod **mods, 
452                      int OpType, int n);
453 int sid_update(LDAP *ldap_handle, char *dn_path);
454 void SwitchSFU(LDAPMod **mods, int *UseSFU30, int n);
455 int check_string(char *s);
456 int check_container_name(char* s);
457
458 int mr_connect_cl(char *server, char *client, int version, int auth);
459 void WriteDomainList();
460 void do_container(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
461              char **before, int beforec, char **after, int afterc);
462 void do_filesys(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
463                 char **before, int beforec, char **after, int afterc);
464 void do_list(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
465              char **before, int beforec, char **after, int afterc);
466 void do_user(LDAP *ldap_handle, char *dn_path, char *ldap_hostname, 
467              char **before, int beforec, char **after, int afterc);
468 void do_member(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
469                char **before, int beforec, char **after, int afterc);
470 void do_mcntmap(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
471                 char **before, int beforec, char **after, int afterc);
472 int linklist_create_entry(char *attribute, char *value,
473                           LK_ENTRY **linklist_entry);
474 int linklist_build(LDAP *ldap_handle, char *dn_path, char *search_exp, 
475                    char **attr_array, LK_ENTRY **linklist_base, 
476                    int *linklist_count, unsigned long ScopeType);
477 void linklist_free(LK_ENTRY *linklist_base);
478
479 int retrieve_attributes(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
480                         char *distinguished_name, LK_ENTRY **linklist_current);
481 int retrieve_entries(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
482                      LK_ENTRY **linklist_base, int *linklist_count);
483 int retrieve_values(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
484                     char *Attribute, char *distinguished_name, 
485                     LK_ENTRY **linklist_current);
486
487 int construct_newvalues(LK_ENTRY *linklist_base, int modvalue_count, 
488                         char *oldValue, char *newValue,
489                         char ***modvalues, int type);
490 void free_values(char **modvalues);
491
492 int convert_domain_to_dn(char *domain, char **bind_path);
493 void get_distinguished_name(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
494                             char *distinguished_name);
495 int moira_disconnect(void);
496 int moira_connect(void);
497 void print_to_screen(const char *fmt, ...);
498 int GetMachineName(char *MachineName);
499 int tickets_get_k5();
500 int get_tickets();
501 int destroy_cache(void);
502 int dest_tkt(void);
503
504 int main(int argc, char **argv)
505 {
506   unsigned long   rc;
507   int             beforec;
508   int             afterc;
509   int             i;
510   int             j;
511   int             k;
512   int             OldUseSFU30;
513   char            *table;
514   char            **before;
515   char            **after;
516   LDAP            *ldap_handle;
517   char            dn_path[256];
518   char            *orig_argv[64];
519
520   whoami = ((whoami = (char *)strrchr(argv[0], '/')) ? whoami+1 : argv[0]);
521
522   if (argc < 4)
523     {
524       com_err(whoami, 0, "Unable to process %s", "argc < 4");
525       exit(1);
526     }
527
528   if (argc < (4 + atoi(argv[2]) + atoi(argv[3])))
529     {
530       com_err(whoami, 0, "Unable to process %s", "argc < (4 + beforec + afterc)");
531       exit(1);
532     }
533
534   if (!strcmp(argv[1], "filesys"))
535     exit(0);
536
537   for (i = 1; i < argc; i++)
538     {
539       strcat(tbl_buf, argv[i]);
540       strcat(tbl_buf, " ");
541     }
542   com_err(whoami, 0, "%s", tbl_buf);
543
544   if (check_winad())
545     {
546       com_err(whoami, 0, "%s failed", "check_winad()");
547       exit(1);
548     }
549
550   if (get_tickets())
551     {
552       com_err(whoami, 0, "%s failed", "get_tickets()");
553       exit(1);
554     }
555
556   initialize_sms_error_table();
557   initialize_krb_error_table();
558
559   UpdateDomainList = 0;
560   memset(DomainNames, '\0', sizeof(DomainNames[0]) * MAX_DOMAINS);
561   if (ReadDomainList())
562     {
563       com_err(whoami, 0, "%s failed", "ReadDomainList()");
564       exit(1);
565     }
566
567   for (i = 0; i < argc; i++)
568      orig_argv[i] = NULL;
569
570   for (k = 0; k < MAX_DOMAINS; k++)
571     {
572       if (strlen(DomainNames[k]) == 0)
573         continue;
574       for (i = 0; i < argc; i++)
575         {
576           if (orig_argv[i] != NULL)
577             free(orig_argv[i]);
578           orig_argv[i] = strdup(argv[i]);
579         }
580
581       memset(PrincipalName, '\0', sizeof(PrincipalName));
582       memset(ldap_domain, '\0', sizeof(ldap_domain));
583       memset(ServerList, '\0', sizeof(ServerList[0]) * MAX_SERVER_NAMES);
584       memset(default_server, '\0', sizeof(default_server));
585       memset(dn_path, '\0', sizeof(dn_path));
586       UseSFU30 = 0;
587       NoChangeConfigFile = 0;
588       beforec = atoi(orig_argv[2]);
589       afterc = atoi(orig_argv[3]);
590       table = orig_argv[1];
591       before = &orig_argv[4];
592       after = &orig_argv[4 + beforec];
593
594       if (afterc == 0)
595         after = NULL;
596
597       if (beforec == 0)
598         before = NULL;
599
600       if (ReadConfigFile(DomainNames[k]))
601         {
602           continue;
603         }
604
605       OldUseSFU30 = UseSFU30;
606
607       for (i = 0; i < 5; i++)
608         {
609           ldap_handle = (LDAP *)NULL;
610           if (!(rc = ad_connect(&ldap_handle, ldap_domain, dn_path, "", "", 
611                                 default_server, 1, ServerList)))
612             {
613               com_err(whoami, 0, "connected to domain %s", DomainNames[k]);
614               break;
615             }
616
617           if (ldap_handle == NULL)
618             {
619               if (!NoChangeConfigFile)
620                 {
621                   for (j = 0; j < MAX_SERVER_NAMES; j++)
622                     {
623                       if (ServerList[j] != NULL)
624                         {
625                           free(ServerList[j]);
626                           ServerList[j] = NULL;
627                         }
628                     }
629                   if (rc = GetServerList(ldap_domain, ServerList))
630                     {
631                       com_err("incremental", 0,
632                               "winad.incr cannot bind to any server in domain %s",
633                               DomainNames[k]);
634                       continue;
635                     }
636                 }
637             }
638         }
639
640       if ((rc) || (ldap_handle == NULL))
641         {
642           critical_alert("incremental",
643                          "winad.incr cannot connect to any server in domain %s",
644                          DomainNames[k]);
645           continue;
646         }
647
648       for (i = 0; i < (int)strlen(table); i++)
649         table[i] = tolower(table[i]);
650
651       if (!strcmp(table, "users"))
652         do_user(ldap_handle, dn_path, ldap_domain, before, beforec, after,
653                 afterc);
654       else if (!strcmp(table, "list"))
655         do_list(ldap_handle, dn_path, ldap_domain, before, beforec, after,
656                 afterc);
657       else if (!strcmp(table, "imembers"))
658         do_member(ldap_handle, dn_path, ldap_domain, before, beforec, after,
659                   afterc);
660       else if (!strcmp(table, "containers"))
661         do_container(ldap_handle, dn_path, ldap_domain, before, beforec, after,
662                      afterc);
663       else if (!strcmp(table, "mcntmap"))
664         do_mcntmap(ldap_handle, dn_path, ldap_domain, before, beforec, after,
665                    afterc);
666       if (!NoChangeConfigFile)
667         GetServerList(ldap_domain, ServerList);
668
669       ad_kdc_disconnect();
670
671       for (i = 0; i < MAX_SERVER_NAMES; i++)
672         {
673           if (ServerList[i] != NULL)
674             {
675               free(ServerList[i]);
676               ServerList[i] = NULL;
677             }
678         }
679
680       rc = ldap_unbind_s(ldap_handle);
681     }
682
683   if (UpdateDomainList == 1)
684     WriteDomainList();
685
686   destroy_cache();
687   exit(0);
688 }
689
690 void do_mcntmap(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
691                 char **before, int beforec, char **after, int afterc)
692 {
693     char    MoiraContainerName[128];
694     char    ADContainerName[128];
695     char    MachineName[1024];
696     char    OriginalMachineName[1024];
697     long    rc;
698     int     DeleteMachine;
699     char    MoiraContainerGroup[64];
700
701     DeleteMachine = 0;
702     memset(ADContainerName, '\0', sizeof(ADContainerName));
703     memset(MoiraContainerName, '\0', sizeof(MoiraContainerName));
704
705     if ((beforec == 0) && (afterc == 0))
706         return;
707
708     if (rc = moira_connect())
709     {
710         critical_alert("AD incremental",
711                        "Error contacting Moira server : %s",
712                        error_message(rc));
713         return;
714     }
715
716     if ((beforec != 0) && (afterc == 0)) /*remove a machine*/
717     {
718         strcpy(OriginalMachineName, before[OU_MACHINE_NAME]);
719         strcpy(MachineName, before[OU_MACHINE_NAME]);
720         strcpy(MoiraContainerGroup, before[OU_CONTAINER_GROUP]);
721         DeleteMachine = 1;
722         com_err(whoami, 0, "removing machine %s from %s", OriginalMachineName, before[OU_CONTAINER_NAME]);
723     }
724     else if ((beforec == 0) && (afterc != 0)) /*add a machine*/
725     {
726         strcpy(OriginalMachineName, after[OU_MACHINE_NAME]);
727         strcpy(MachineName, after[OU_MACHINE_NAME]);
728         strcpy(MoiraContainerGroup, after[OU_CONTAINER_GROUP]);
729         com_err(whoami, 0, "adding machine %s to container %s", OriginalMachineName, after[OU_CONTAINER_NAME]);
730     }
731     else
732       {
733         moira_disconnect();
734         return;
735       }
736
737     rc = GetMachineName(MachineName);
738     if (strlen(MachineName) == 0)
739     {
740         moira_disconnect();
741         com_err(whoami, 0, "Unable to find alais for machine %s in Moira", OriginalMachineName);
742         return;
743     }
744     Moira_process_machine_container_group(MachineName, MoiraContainerGroup,
745                                           DeleteMachine);
746     if (machine_check(ldap_handle, dn_path, MachineName))
747     {
748         com_err(whoami, 0, "Unable to find machine %s (alias %s) in AD.", OriginalMachineName, MachineName);
749         moira_disconnect();
750         return;
751     }
752     memset(MoiraContainerName, '\0', sizeof(MoiraContainerName));
753     machine_get_moira_container(ldap_handle, dn_path, MachineName, MoiraContainerName);
754     if (strlen(MoiraContainerName) == 0)
755     {
756         com_err(whoami, 0, "Unable to fine machine %s (alias %s) container in Moira - moving to orphans OU.",
757                 OriginalMachineName, MachineName);
758         machine_move_to_ou(ldap_handle, dn_path, MachineName, orphans_machines_ou);
759         moira_disconnect();
760         return;
761     }
762     container_get_dn(MoiraContainerName, ADContainerName);
763     if (MoiraContainerName[strlen(MoiraContainerName) - 1] != '/')
764        strcat(MoiraContainerName, "/");
765     container_check(ldap_handle, dn_path, MoiraContainerName);
766     machine_move_to_ou(ldap_handle, dn_path, MachineName, ADContainerName);
767     moira_disconnect();
768     return;
769 }
770
771 void do_container(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
772              char **before, int beforec, char **after, int afterc)
773 {
774   long rc;
775
776   if ((beforec == 0) && (afterc == 0))
777     return;
778
779   if (rc = moira_connect())
780     {
781       critical_alert("AD incremental", "Error contacting Moira server : %s",
782                      error_message(rc));
783       return;
784     }
785
786   if ((beforec != 0) && (afterc == 0)) /*delete a new container*/
787     {
788       com_err(whoami, 0, "deleting container %s", before[CONTAINER_NAME]);
789       container_delete(ldap_handle, dn_path, beforec, before);
790       Moira_container_group_delete(before);
791       moira_disconnect();
792       return;
793     }
794   if ((beforec == 0) && (afterc != 0)) /*create a container*/
795     {
796       com_err(whoami, 0, "creating container %s", after[CONTAINER_NAME]);
797       container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
798       container_create(ldap_handle, dn_path, afterc, after);
799       Moira_container_group_create(after);
800       moira_disconnect();
801       return;
802     }
803
804   if (strcasecmp(before[CONTAINER_NAME], after[CONTAINER_NAME]))
805     {
806       com_err(whoami, 0, "renaming container %s to %s", before[CONTAINER_NAME], after[CONTAINER_NAME]);
807       container_rename(ldap_handle, dn_path, beforec, before, afterc, after);
808       Moira_container_group_update(before, after);
809       moira_disconnect();
810       return;
811     }
812   com_err(whoami, 0, "updating container %s information", after[CONTAINER_NAME]);
813   container_update(ldap_handle, dn_path, beforec, before, afterc, after);
814   Moira_container_group_update(before, after);
815   moira_disconnect();
816   return;
817 }
818
819
820 #define L_LIST_DESC 9
821 #define L_LIST_ID   10
822
823 void do_list(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
824              char **before, int beforec, char **after, int afterc)
825 {
826   int   updateGroup;
827   int   ProcessGroup;
828   long  rc;
829   char  group_membership[6];
830   char  list_id[32];
831   int   security_flag;
832   char  filter[128];
833   char  group_ou[256];
834   char  before_list_id[32];
835   char  before_group_membership[1];
836   int   before_security_flag;
837   char  before_group_ou[256];
838   LK_ENTRY *ptr = NULL;
839
840   if (beforec == 0 && afterc == 0)
841     return;
842
843   memset(list_id, '\0', sizeof(list_id));
844   memset(before_list_id, '\0', sizeof(before_list_id));
845   memset(before_group_ou, '\0', sizeof(before_group_ou));
846   memset(before_group_membership, '\0', sizeof(before_group_membership));
847   memset(group_ou, '\0', sizeof(group_ou));
848   memset(group_membership, '\0', sizeof(group_membership));
849   updateGroup = 0;
850
851   if (beforec > L_GID)
852     {
853       if (beforec < L_LIST_ID)
854         return;
855       if (beforec > L_LIST_DESC)
856         {
857           strcpy(before_list_id, before[L_LIST_ID]);
858         }
859       before_security_flag = 0;
860       get_group_membership(before_group_membership, before_group_ou, &before_security_flag, before);
861     }
862   if (afterc > L_GID)
863     {
864       if (afterc < L_LIST_ID)
865         return;
866       if (afterc > L_LIST_DESC)
867         {
868           strcpy(list_id, after[L_LIST_ID]);
869         }
870       security_flag = 0;
871       get_group_membership(group_membership, group_ou, &security_flag, after);
872     }
873
874   if ((beforec == 0) && (afterc == 0)) /*this case should never happen*/
875     return;
876
877   updateGroup = 0;
878   if (beforec)
879     {
880       updateGroup = 1;
881       if ((rc = process_group(ldap_handle, dn_path, before_list_id, before[L_NAME], 
882                               before_group_ou, before_group_membership, 
883                               before_security_flag, CHECK_GROUPS)))
884         {
885           if (rc == AD_NO_GROUPS_FOUND)
886             updateGroup = 0;
887           else
888             {
889               if ((rc == AD_WRONG_GROUP_DN_FOUND) || (rc == AD_MULTIPLE_GROUPS_FOUND))
890                 {
891                   rc = process_group(ldap_handle, dn_path, before_list_id, before[L_NAME], 
892                                      before_group_ou, before_group_membership, 
893                                      before_security_flag, CLEANUP_GROUPS);
894                 }
895               if ((rc != AD_NO_GROUPS_FOUND) && (rc != 0))
896                 {
897                   com_err(whoami, 0, "Unable to process list %s",
898                           before[L_NAME]);
899                   return;
900                 }
901               if (rc == AD_NO_GROUPS_FOUND)
902                 updateGroup = 0;
903             }
904         }
905     }
906   
907   if ((beforec != 0) && (afterc != 0))
908     {
909       if (((strcmp(after[L_NAME], before[L_NAME])) || 
910           ((!strcmp(after[L_NAME], before[L_NAME])) && 
911            (strcmp(before_group_ou, group_ou)))) &&
912           (updateGroup == 1))
913         {
914           com_err(whoami, 0, "Changing list name from %s to %s",
915                   before[L_NAME], after[L_NAME]);
916           if ((strlen(before_group_ou) == 0) || (strlen(before_group_membership) == 0) ||
917               (strlen(group_ou) == 0) || (strlen(group_membership) == 0))
918             {
919               com_err(whoami, 0, "%s", "Unable to find the group OU's");
920               return;
921             }
922           memset(filter, '\0', sizeof(filter));
923           if ((rc = group_rename(ldap_handle, dn_path, 
924                                  before[L_NAME], before_group_membership, 
925                                  before_group_ou, before_security_flag, before[L_LIST_DESC],
926                                  after[L_NAME], group_membership, 
927                                  group_ou, security_flag, after[L_LIST_DESC],
928                                  list_id, filter)))
929             {
930               if (rc != AD_NO_GROUPS_FOUND)
931                 {
932                   com_err(whoami, 0, "Unable to change list name from %s to %s",
933                           before[L_NAME], after[L_NAME]);
934                   return;
935                 }
936               updateGroup = 0;
937             }
938           beforec = 0;
939         }
940       else
941         beforec = 0;
942     }
943
944   if (beforec)
945     {
946       if ((strlen(before_group_ou) == 0) || (strlen(before_group_membership) == 0))
947         {
948           com_err(whoami, 0, "Unable to find the group OU for group %s", before[L_NAME]);
949           return;
950         }
951       com_err(whoami, 0, "Deleting group %s", before[L_NAME]);
952       rc = group_delete(ldap_handle, dn_path, before[L_NAME], 
953                         before_group_membership, before_list_id);
954       return;
955     }
956   if (afterc)
957     {
958       if (!updateGroup)
959         {
960           com_err(whoami, 0, "Creating group %s", after[L_NAME]);
961           if (rc = process_group(ldap_handle, dn_path, list_id, after[L_NAME], 
962                                   group_ou, group_membership, 
963                                   security_flag, CHECK_GROUPS))
964             {
965               if (rc != AD_NO_GROUPS_FOUND)
966                 {
967                   if ((rc == AD_WRONG_GROUP_DN_FOUND) || (rc == AD_MULTIPLE_GROUPS_FOUND))
968                     {
969                       rc = process_group(ldap_handle, dn_path, list_id, after[L_NAME], 
970                                          group_ou, group_membership, 
971                                          security_flag, CLEANUP_GROUPS);
972                     }
973                   if (rc)
974                     {
975                       com_err(whoami, 0, "Unable to create list %s", after[L_NAME]);
976                       return;
977                     }
978                 }
979             }
980         }
981       else
982         com_err(whoami, 0, "Updating group %s information", after[L_NAME]);
983
984       if (rc = moira_connect())
985         {
986           critical_alert("AD incremental",
987                          "Error contacting Moira server : %s",
988                          error_message(rc));
989           return;
990         }
991
992       ProcessGroup = 0;
993       if (ProcessAce(ldap_handle, dn_path, after[L_NAME], "LIST", 0, &ProcessGroup))
994         return;
995       if (ProcessGroup)
996         {
997           if (ProcessAce(ldap_handle, dn_path, after[L_NAME], "LIST", 1, &ProcessGroup))
998             return;
999         }
1000       if (make_new_group(ldap_handle, dn_path, list_id, after[L_NAME], 
1001                          group_ou, group_membership, security_flag, updateGroup))
1002         {
1003           moira_disconnect();
1004           return;
1005         }
1006       if (atoi(after[L_ACTIVE]))
1007         {
1008           populate_group(ldap_handle, dn_path, after[L_NAME], group_ou, 
1009                          group_membership, security_flag, list_id);
1010         }
1011       moira_disconnect();
1012     }
1013   return;
1014 }
1015
1016 #define LM_EXTRA_ACTIVE   (LM_END)
1017 #define LM_EXTRA_PUBLIC   (LM_END+1)
1018 #define LM_EXTRA_HIDDEN   (LM_END+2)
1019 #define LM_EXTRA_MAILLIST (LM_END+3)
1020 #define LM_EXTRA_GROUP    (LM_END+4)
1021 #define LM_EXTRA_GID      (LM_END+5)
1022 #define LMN_LIST_ID       (LM_END+6)
1023 #define LM_LIST_ID        (LM_END+7)
1024 #define LM_USER_ID        (LM_END+8)
1025 #define LM_EXTRA_END      (LM_END+9)
1026
1027 void do_member(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
1028                char **before, int beforec, char **after, int afterc)
1029 {
1030   char  group_name[128];
1031   char  user_name[128];
1032   char  user_type[128];
1033   char  moira_list_id[32];
1034   char  moira_user_id[32];
1035   char  group_membership[1];
1036   char  group_ou[256];
1037   char  machine_ou[256];
1038   char  *args[16];
1039   char  **ptr;
1040   char  *av[7];
1041   char  *call_args[7];
1042   char  *pUserOu;
1043   char  NewMachineName[1024];
1044   int   security_flag;
1045   int   rc;
1046   int   ProcessGroup;
1047
1048   pUserOu = NULL;
1049   ptr = NULL;
1050   memset(moira_list_id, '\0', sizeof(moira_list_id));
1051   memset(moira_user_id, '\0', sizeof(moira_user_id));
1052   if (afterc)
1053     {
1054       if (afterc < LM_EXTRA_GID)
1055         return;
1056       if (!atoi(after[LM_EXTRA_ACTIVE]))
1057         {
1058         com_err(whoami, 0, "Unable to add %s to group %s : group not active", after[2], after[0]);
1059         return;
1060         }
1061       ptr = after;
1062       if (!strcasecmp(ptr[LM_TYPE], "LIST"))
1063         return;
1064       strcpy(user_name, after[LM_MEMBER]);
1065       strcpy(group_name, after[LM_LIST]);
1066       strcpy(user_type, after[LM_TYPE]);
1067       if (!strcasecmp(ptr[LM_TYPE], "MACHINE"))
1068         {
1069           if (afterc > LM_EXTRA_GROUP)
1070             {
1071               strcpy(moira_list_id, after[LMN_LIST_ID]);
1072               strcpy(moira_user_id, after[LM_LIST_ID]);
1073             }
1074         }
1075       else if (!strcasecmp(ptr[LM_TYPE], "USER"))
1076         {
1077           if (afterc > LMN_LIST_ID)
1078             {
1079               strcpy(moira_list_id, after[LM_LIST_ID]);
1080               strcpy(moira_user_id, after[LM_USER_ID]);
1081             }
1082         }
1083       else
1084         {
1085           if (afterc > LM_EXTRA_GID)
1086             strcpy(moira_list_id, after[LMN_LIST_ID]);
1087         }
1088     }
1089   else if (beforec)
1090     {
1091       if (beforec < LM_EXTRA_GID)
1092         return;
1093       if (!atoi(before[LM_EXTRA_ACTIVE]))
1094         {
1095           com_err(whoami, 0, "Unable to add %s to group %s : group not active", before[2], before[0]);
1096           return;
1097         }
1098       ptr = before;
1099       if (!strcasecmp(ptr[LM_TYPE], "LIST"))
1100         return;
1101       strcpy(user_name, before[LM_MEMBER]);
1102       strcpy(group_name, before[LM_LIST]);
1103       strcpy(user_type, before[LM_TYPE]);
1104       if (!strcasecmp(ptr[LM_TYPE], "MACHINE"))
1105         {
1106           if (beforec > LM_EXTRA_GROUP)
1107             {
1108               strcpy(moira_list_id, before[LMN_LIST_ID]);
1109               strcpy(moira_user_id, before[LM_LIST_ID]);
1110             }
1111         }
1112       else if (!strcasecmp(ptr[LM_TYPE], "USER"))
1113         {
1114           if (beforec > LMN_LIST_ID)
1115             {
1116               strcpy(moira_list_id, before[LM_LIST_ID]);
1117               strcpy(moira_user_id, before[LM_USER_ID]);
1118             }
1119         }
1120       else
1121         {
1122           if (beforec > LM_EXTRA_GID)
1123             strcpy(moira_list_id, before[LMN_LIST_ID]);
1124         }
1125     }
1126
1127   if (ptr == NULL)
1128     {
1129       com_err(whoami, 0, "Unable to process group : beforec = %d, afterc = %d", beforec, afterc);
1130       return;
1131     }
1132
1133   args[L_NAME] = ptr[LM_LIST];
1134   args[L_ACTIVE] = ptr[LM_EXTRA_ACTIVE];
1135   args[L_PUBLIC] = ptr[LM_EXTRA_PUBLIC];
1136   args[L_HIDDEN] = ptr[LM_EXTRA_HIDDEN];
1137   args[L_MAILLIST] = ptr[LM_EXTRA_MAILLIST];
1138   args[L_GROUP] = ptr[LM_EXTRA_GROUP];
1139   args[L_GID] = ptr[LM_EXTRA_GID];
1140
1141   security_flag = 0;
1142   memset(group_ou, '\0', sizeof(group_ou));
1143   get_group_membership(group_membership, group_ou, &security_flag, args);
1144   if (strlen(group_ou) == 0)
1145     {
1146       com_err(whoami, 0, "Unable to find the group OU for group %s", group_name);
1147       return;
1148     }
1149   if (rc = process_group(ldap_handle, dn_path, moira_list_id, group_name, group_ou, group_membership, security_flag, CHECK_GROUPS))
1150     {
1151       if (rc != AD_NO_GROUPS_FOUND)
1152         {
1153           if (rc = process_group(ldap_handle, dn_path, moira_list_id, group_name, group_ou, group_membership, security_flag, CLEANUP_GROUPS))
1154             {
1155               if (rc != AD_NO_GROUPS_FOUND)
1156                 {
1157                   if (afterc)
1158                     com_err(whoami, 0, "Unable to add %s to group %s - unable to process group", user_name, group_name);
1159                   else
1160                     com_err(whoami, 0, "Unable to remove %s from group %s - unable to process group", user_name, group_name);
1161                   return;
1162                 }
1163             }
1164         }
1165     }
1166   if (rc == AD_NO_GROUPS_FOUND)
1167     {
1168       if (rc = moira_connect())
1169         {
1170           critical_alert("AD incremental",
1171                          "Error contacting Moira server : %s",
1172                          error_message(rc));
1173           return;
1174         }
1175
1176       com_err(whoami, 0, "creating group %s", group_name);
1177       ProcessGroup = 0;
1178       if (ProcessAce(ldap_handle, dn_path, ptr[LM_LIST], "LIST", 0, &ProcessGroup))
1179         return;
1180       if (ProcessGroup)
1181         {
1182           if (ProcessAce(ldap_handle, dn_path, ptr[LM_LIST], "LIST", 1, &ProcessGroup))
1183             return;
1184         }
1185       if (make_new_group(ldap_handle, dn_path, moira_list_id, ptr[LM_LIST], 
1186                          group_ou, group_membership, security_flag, 0))
1187         {
1188           moira_disconnect();
1189           return;
1190         }
1191       if (atoi(ptr[LM_EXTRA_ACTIVE]))
1192         {
1193           populate_group(ldap_handle, dn_path, ptr[LM_LIST], group_ou, 
1194                          group_membership, security_flag, moira_list_id);
1195         }
1196       moira_disconnect();
1197     }
1198   rc = 0;
1199   if (beforec)
1200     {
1201       com_err(whoami, 0, "removing user %s from list %s", user_name, group_name);
1202       pUserOu = user_ou;
1203       if (!strcasecmp(ptr[LM_TYPE], "MACHINE"))
1204         {
1205           memset(machine_ou, '\0', sizeof(machine_ou));
1206           memset(NewMachineName, '\0', sizeof(NewMachineName));
1207           if (get_machine_ou(ldap_handle, dn_path, ptr[LM_MEMBER], machine_ou, NewMachineName))
1208             return;
1209           if (ptr[LM_MEMBER] != NULL)     
1210             free(ptr[LM_MEMBER]);
1211           ptr[LM_MEMBER] = strdup(NewMachineName);
1212           pUserOu = machine_ou;
1213         }
1214       if (!strcasecmp(ptr[LM_TYPE], "STRING"))
1215         {
1216           if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], contact_ou))
1217             return;
1218           pUserOu = contact_ou;
1219         }
1220       else if (!strcasecmp(ptr[LM_TYPE], "KERBEROS"))
1221         {
1222           if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], kerberos_ou))
1223             return;
1224           pUserOu = kerberos_ou;
1225         }
1226       if (rc = member_remove(ldap_handle, dn_path, group_name,
1227                              group_ou, group_membership, ptr[LM_MEMBER], 
1228                              pUserOu, moira_list_id))
1229           com_err(whoami, 0, "Unable to remove %s from group %s", user_name, group_name);
1230       return;
1231     }
1232
1233   com_err(whoami, 0, "Adding %s to list %s", user_name, group_name);
1234   pUserOu = user_ou;
1235
1236   if (!strcasecmp(ptr[LM_TYPE], "MACHINE"))
1237     {
1238       memset(machine_ou, '\0', sizeof(machine_ou));
1239       memset(NewMachineName, '\0', sizeof(NewMachineName));
1240       if (get_machine_ou(ldap_handle, dn_path, ptr[LM_MEMBER], machine_ou, NewMachineName))
1241         return;
1242       if (ptr[LM_MEMBER] != NULL)
1243         free(ptr[LM_MEMBER]);
1244       ptr[LM_MEMBER] = strdup(NewMachineName);
1245       pUserOu = machine_ou;
1246     }
1247   else if (!strcasecmp(ptr[LM_TYPE], "STRING"))
1248     {
1249       if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], contact_ou))
1250         return;
1251       pUserOu = contact_ou;
1252     }
1253   else if (!strcasecmp(ptr[LM_TYPE], "KERBEROS"))
1254     {
1255       if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], kerberos_ou))
1256         return;
1257       pUserOu = kerberos_ou;
1258     }
1259   else if (!strcasecmp(ptr[LM_TYPE], "USER"))
1260     {
1261       if ((rc = check_user(ldap_handle, dn_path, ptr[LM_MEMBER], 
1262                            moira_user_id)) == AD_NO_USER_FOUND)
1263         {
1264           if (rc = moira_connect())
1265             {
1266               critical_alert("AD incremental", 
1267                              "Error connection to Moira : %s",
1268                              error_message(rc));
1269               return;
1270             }
1271           com_err(whoami, 0, "creating user %s", after[U_NAME]);
1272           av[0] = ptr[LM_MEMBER];
1273           call_args[0] = (char *)ldap_handle;
1274           call_args[1] = dn_path;
1275           call_args[2] = moira_user_id;
1276           call_args[3] = NULL;
1277
1278           callback_rc = 0;
1279           if (rc = mr_query("get_user_account_by_login", 1, av, user_create,
1280                             call_args))
1281             {
1282               moira_disconnect();
1283               com_err(whoami, 0, "Unable to create user %s : %s",
1284                       ptr[LM_MEMBER], error_message(rc));
1285               return;
1286             }
1287           if (callback_rc)
1288             {
1289               moira_disconnect();
1290               com_err(whoami, 0, "Unable to create user %s", ptr[LM_MEMBER]);
1291               return;
1292             }
1293         }
1294       else
1295         {
1296           if (rc != 0)
1297             return;
1298         }
1299       pUserOu = user_ou;
1300     }
1301
1302   if (rc = member_add(ldap_handle, dn_path, group_name,
1303                   group_ou, group_membership, ptr[LM_MEMBER],
1304                   pUserOu, moira_list_id))
1305     {
1306       com_err(whoami, 0, "Unable to add %s to group %s", user_name, group_name);
1307     }
1308   return;
1309 }
1310
1311
1312 #define U_USER_ID    10
1313 #define U_HOMEDIR    11
1314 #define U_PROFILEDIR 12
1315 #define U_POTYPE     13
1316
1317 void do_user(LDAP *ldap_handle, char *dn_path, char *ldap_hostname, 
1318              char **before, int beforec, char **after, 
1319              int afterc)
1320 {
1321   int   rc;
1322   char  *av[7];
1323   char  after_user_id[32];
1324   char  before_user_id[32];
1325   char  *call_args[7];
1326
1327   if ((beforec == 0) && (afterc == 0))
1328     return;
1329
1330   memset(after_user_id, '\0', sizeof(after_user_id));
1331   memset(before_user_id, '\0', sizeof(before_user_id));
1332   if (beforec > U_USER_ID)
1333     strcpy(before_user_id, before[U_USER_ID]);
1334   if (afterc > U_USER_ID)
1335     strcpy(after_user_id, after[U_USER_ID]);
1336
1337   if ((beforec == 0) && (afterc == 0)) /*this case should never happen */
1338     return;
1339
1340   if ((beforec == 0) && (afterc != 0)) 
1341     {
1342       /*this case only happens when the account*/
1343       /*account is first created but not usable*/
1344       com_err(whoami, 0, "Unable to process user %s because the user account is not yet usable", after[U_NAME]);
1345       return;
1346     }
1347   if ((beforec != 0) && (afterc == 0)) /*this case only happens when the account*/
1348     {                                  /*is expunged*/
1349       if (atoi(before[U_STATE]) == 0)
1350         {
1351           com_err(whoami, 0, "expunging user %s from AD", before[U_NAME]);
1352           user_delete(ldap_handle, dn_path, before[U_NAME], before_user_id);
1353         }
1354       else
1355         {
1356           com_err(whoami, 0, "Unable to process because user %s has been previously expungeded", before[U_NAME]);
1357         }
1358       return;
1359     }
1360
1361   /*process anything that gets here*/
1362   if ((rc = check_user(ldap_handle, dn_path, before[U_NAME], 
1363                        before_user_id)) == AD_NO_USER_FOUND)
1364     {
1365       if (!check_string(after[U_NAME]))
1366         return;
1367       if (rc = moira_connect())
1368         {
1369           critical_alert("AD incremental", 
1370                          "Error connection to Moira : %s",
1371                          error_message(rc));
1372           return;
1373         }
1374       com_err(whoami, 0, "creating user %s", after[U_NAME]);
1375
1376       av[0] = after[U_NAME];
1377       call_args[0] = (char *)ldap_handle;
1378       call_args[1] = dn_path;
1379       call_args[2] = after_user_id;
1380       call_args[3] = NULL;
1381       callback_rc = 0;
1382       if (rc = mr_query("get_user_account_by_login", 1, av, user_create,
1383                         call_args))
1384         {
1385           moira_disconnect();
1386           com_err(whoami, 0, "Unable to create user %s : %s",
1387                   after[U_NAME], error_message(rc));
1388           return;
1389         }
1390       if (callback_rc)
1391         {
1392           moira_disconnect();
1393           com_err(whoami, 0, "Unable to create user %s", after[U_NAME]);
1394           return;
1395         }
1396       return;
1397     }
1398   else
1399     {
1400       if (rc != 0)
1401         return;
1402     }
1403   if (strcmp(before[U_NAME], after[U_NAME]))
1404     {
1405       if ((check_string(before[U_NAME])) && (check_string(after[U_NAME])))
1406         {
1407           com_err(whoami, 0, "changing user %s to %s", 
1408                   before[U_NAME], after[U_NAME]);
1409           if ((rc = user_rename(ldap_handle, dn_path, before[U_NAME], 
1410                                 after[U_NAME])) != LDAP_SUCCESS)
1411             {
1412               return;
1413             }
1414         }
1415     }
1416   com_err(whoami, 0, "updating user %s information", after[U_NAME]);
1417   rc = user_update(ldap_handle, dn_path, after[U_NAME],
1418                    after[U_UID], after[U_MITID], 
1419                    after_user_id, atoi(after[U_STATE]),
1420                    after[U_HOMEDIR], after[U_PROFILEDIR]);
1421   return;
1422 }
1423
1424 int construct_newvalues(LK_ENTRY *linklist_base, int modvalue_count, 
1425                         char *oldValue, char *newValue,
1426                         char ***modvalues, int type)
1427 {
1428   LK_ENTRY    *linklist_ptr;
1429   int         i;
1430   char        *cPtr;
1431
1432   if (((*modvalues) = calloc(1, (modvalue_count + 1) * sizeof(char *)))
1433       == NULL)
1434     {
1435       return(1);
1436     }
1437   for (i = 0; i < (modvalue_count + 1); i++)
1438     (*modvalues)[i] = NULL;
1439   if (modvalue_count != 0)
1440     {
1441       linklist_ptr = linklist_base;
1442       for (i = 0; i < modvalue_count; i++)
1443         {
1444           if ((oldValue != NULL) && (newValue != NULL))
1445             {
1446               if ((cPtr = (char *)strstr(linklist_ptr->value, oldValue))
1447                  != (char *)NULL)
1448                 {
1449                   if (type == REPLACE)
1450                     {
1451                       if (((*modvalues)[i] = calloc(1, strlen(newValue) + 1))
1452                           == NULL)
1453                         return(1);
1454                       memset((*modvalues)[i], '\0', strlen(newValue) + 1);
1455                       strcpy((*modvalues)[i], newValue);
1456                     }
1457                   else
1458                     {
1459                       if (((*modvalues)[i] = calloc(1, 
1460                                         (int)(cPtr - linklist_ptr->value) + 
1461                                         (linklist_ptr->length - strlen(oldValue)) + 
1462                                         strlen(newValue) + 1)) == NULL)
1463                         return(1);
1464                       memset((*modvalues)[i], '\0', 
1465                              (int)(cPtr - linklist_ptr->value) + 
1466                              (linklist_ptr->length - strlen(oldValue)) + 
1467                              strlen(newValue) + 1);
1468                       memcpy((*modvalues)[i], linklist_ptr->value, 
1469                              (int)(cPtr - linklist_ptr->value));
1470                       strcat((*modvalues)[i], newValue);
1471                       strcat((*modvalues)[i], 
1472      &linklist_ptr->value[(int)(cPtr - linklist_ptr->value) + strlen(oldValue)]);
1473                     }
1474                 }
1475               else
1476                 {
1477                   (*modvalues)[i] = calloc(1, linklist_ptr->length + 1);
1478                   memset((*modvalues)[i], '\0', linklist_ptr->length + 1);
1479                   memcpy((*modvalues)[i], linklist_ptr->value,
1480                          linklist_ptr->length);
1481                 }
1482             }
1483         else
1484             {
1485               (*modvalues)[i] = calloc(1, linklist_ptr->length + 1);
1486               memset((*modvalues)[i], '\0', linklist_ptr->length + 1);
1487               memcpy((*modvalues)[i], linklist_ptr->value,
1488                      linklist_ptr->length);
1489             }
1490           linklist_ptr = linklist_ptr->next;
1491         }
1492       (*modvalues)[i] = NULL;
1493     }
1494   return(0);
1495 }
1496
1497
1498 int linklist_build(LDAP *ldap_handle, char *dn_path, char *search_exp, 
1499                    char **attr_array, LK_ENTRY **linklist_base,
1500                    int *linklist_count, unsigned long ScopeType)
1501 {
1502   ULONG       rc;
1503   LDAPMessage *ldap_entry;
1504
1505   rc = 0;
1506   ldap_entry = NULL;
1507   (*linklist_base) = NULL;
1508   (*linklist_count) = 0;
1509   if ((rc = ldap_search_s(ldap_handle, dn_path, ScopeType, 
1510                           search_exp, attr_array, 0, &ldap_entry))
1511       != LDAP_SUCCESS)
1512       {
1513         if (rc != LDAP_SIZELIMIT_EXCEEDED)
1514           return(0);
1515       }
1516
1517   rc = retrieve_entries(ldap_handle, ldap_entry, linklist_base, linklist_count);
1518
1519   ldap_msgfree(ldap_entry);
1520   return(rc);
1521 }
1522
1523
1524 int retrieve_entries(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
1525                      LK_ENTRY **linklist_base, int *linklist_count)
1526 {
1527   char        distinguished_name[1024];
1528   LK_ENTRY    *linklist_ptr;
1529   int         rc;
1530
1531   if ((ldap_entry = ldap_first_entry(ldap_handle, ldap_entry)) == NULL)
1532     return(0);
1533
1534   memset(distinguished_name, '\0', sizeof(distinguished_name));
1535   get_distinguished_name(ldap_handle, ldap_entry, distinguished_name);
1536
1537   if ((rc = retrieve_attributes(ldap_handle, ldap_entry, distinguished_name,
1538                                 linklist_base)) != 0)
1539     return(rc);
1540
1541   while ((ldap_entry = ldap_next_entry(ldap_handle, ldap_entry)) != NULL)
1542     {
1543       memset(distinguished_name, '\0', sizeof(distinguished_name));
1544       get_distinguished_name(ldap_handle, ldap_entry, distinguished_name);
1545
1546       if ((rc = retrieve_attributes(ldap_handle, ldap_entry, distinguished_name,
1547                                     linklist_base)) != 0)
1548         return(rc);
1549     }
1550
1551   linklist_ptr = (*linklist_base);
1552   (*linklist_count) = 0;
1553   while (linklist_ptr != NULL)
1554     {
1555       ++(*linklist_count);
1556       linklist_ptr = linklist_ptr->next;
1557     }
1558   return(0);
1559 }
1560
1561 int retrieve_attributes(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
1562                         char *distinguished_name, LK_ENTRY **linklist_current)
1563 {
1564   char        *Attribute;
1565   BerElement  *ptr;
1566
1567   ptr = NULL;
1568   if ((Attribute = ldap_first_attribute(ldap_handle, ldap_entry, &ptr)) != NULL)
1569     {
1570       retrieve_values(ldap_handle, ldap_entry, Attribute, distinguished_name,
1571                       linklist_current);
1572       ldap_memfree(Attribute);
1573       while ((Attribute = ldap_next_attribute(ldap_handle, ldap_entry, 
1574                                               ptr)) != NULL)
1575         {
1576           retrieve_values(ldap_handle, ldap_entry, Attribute,
1577                           distinguished_name, linklist_current);
1578           ldap_memfree(Attribute);
1579         }
1580     }
1581   ldap_ber_free(ptr, 0);
1582   return(0);
1583 }
1584
1585 int retrieve_values(LDAP *ldap_handle, LDAPMessage *ldap_entry,
1586                     char *Attribute, char *distinguished_name,
1587                     LK_ENTRY **linklist_current)
1588 {
1589   char        **str_value;
1590   char        temp[256];
1591   void        **Ptr;
1592   int         use_bervalue;
1593   LK_ENTRY    *linklist_previous;
1594   LDAP_BERVAL **ber_value;
1595   DWORD       ber_length;
1596 #ifdef LDAP_DEBUG
1597   SID         *sid;
1598   GUID        *guid;
1599   int         i;
1600   int         intValue;
1601   DWORD       *subauth;
1602   SID_IDENTIFIER_AUTHORITY    *sid_auth;
1603   unsigned char   *subauth_count;
1604 #endif /*LDAP_BEGUG*/
1605
1606   use_bervalue = 0;
1607   memset(temp, '\0', sizeof(temp));
1608   if ((!strcmp(Attribute, "objectSid")) ||
1609       (!strcmp(Attribute, "objectGUID")))
1610     use_bervalue = 1;
1611
1612   if (use_bervalue)
1613     {
1614       ber_value = ldap_get_values_len(ldap_handle, ldap_entry, Attribute);
1615       Ptr = (void **)ber_value;
1616       str_value = NULL;
1617       }
1618   else
1619     {
1620       str_value = ldap_get_values(ldap_handle, ldap_entry, Attribute);
1621       Ptr = (void **)str_value;
1622       ber_value = NULL;
1623     }
1624   if (Ptr != NULL)
1625     {
1626       for (; *Ptr; Ptr++) 
1627         {
1628           if ((linklist_previous = calloc(1, sizeof(LK_ENTRY))) == NULL)
1629             return(1);
1630           memset(linklist_previous, '\0', sizeof(LK_ENTRY));
1631           linklist_previous->next = (*linklist_current);
1632           (*linklist_current) = linklist_previous;
1633
1634           if (((*linklist_current)->attribute = calloc(1, 
1635                                                strlen(Attribute) + 1)) == NULL)
1636             return(1);
1637           memset((*linklist_current)->attribute, '\0', strlen(Attribute) + 1);
1638           strcpy((*linklist_current)->attribute, Attribute);
1639           if (use_bervalue)
1640             {
1641               ber_length = (*(LDAP_BERVAL **)Ptr)->bv_len;
1642               if (((*linklist_current)->value = calloc(1, ber_length)) == NULL)
1643                 return(1);
1644               memset((*linklist_current)->value, '\0', ber_length);
1645               memcpy((*linklist_current)->value, (*(LDAP_BERVAL **)Ptr)->bv_val, 
1646                                                   ber_length);
1647               (*linklist_current)->length = ber_length;
1648             }
1649           else
1650             {
1651               if (((*linklist_current)->value = calloc(1, 
1652                                                   strlen(*Ptr) + 1)) == NULL)
1653                 return(1);
1654               memset((*linklist_current)->value, '\0', strlen(*Ptr) + 1);
1655               (*linklist_current)->length = strlen(*Ptr);
1656               strcpy((*linklist_current)->value, *Ptr);
1657             }
1658           (*linklist_current)->ber_value = use_bervalue;
1659           if (((*linklist_current)->dn = calloc(1, 
1660                                       strlen(distinguished_name) + 1)) == NULL)
1661             return(1);
1662           memset((*linklist_current)->dn, '\0', strlen(distinguished_name) + 1);
1663           strcpy((*linklist_current)->dn, distinguished_name);
1664
1665 #ifdef LDAP_DEBUG
1666           if (!strcmp(Attribute, "objectGUID"))
1667             {
1668               guid = (GUID *)((*linklist_current)->value);
1669               sprintf(temp, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 
1670                       guid->Data1, guid->Data2, guid->Data3, 
1671                       guid->Data4[0], guid->Data4[1], guid->Data4[2], 
1672                       guid->Data4[3], guid->Data4[4], guid->Data4[5], 
1673                       guid->Data4[6], guid->Data4[7]);
1674               print_to_screen("     %20s : {%s}\n", Attribute, temp);
1675             }
1676           else if (!strcmp(Attribute, "objectSid"))
1677             {
1678               sid = (SID *)((*(LDAP_BERVAL **)Ptr)->bv_val);
1679 #ifdef _WIN32
1680               print_to_screen("        Revision = %d\n", sid->Revision);
1681               print_to_screen("        SID Identifier Authority:\n");
1682               sid_auth = &sid->IdentifierAuthority;
1683               if (sid_auth->Value[0])
1684                 print_to_screen("            SECURITY_NULL_SID_AUTHORITY\n");
1685               else if (sid_auth->Value[1])
1686                 print_to_screen("            SECURITY_WORLD_SID_AUTHORITY\n");
1687               else if (sid_auth->Value[2])
1688                 print_to_screen("            SECURITY_LOCAL_SID_AUTHORITY\n");
1689               else if (sid_auth->Value[3])
1690                 print_to_screen("            SECURITY_CREATOR_SID_AUTHORITY\n");
1691               else if (sid_auth->Value[5])
1692                 print_to_screen("            SECURITY_NT_AUTHORITY\n");
1693               else
1694                 print_to_screen("            UNKNOWN SID AUTHORITY\n");
1695               subauth_count = GetSidSubAuthorityCount(sid);
1696               print_to_screen("        SidSubAuthorityCount = %d\n", 
1697                               *subauth_count);
1698               print_to_screen("        SidSubAuthority:\n");
1699               for (i = 0; i < *subauth_count; i++)
1700                 {
1701                   if ((subauth = GetSidSubAuthority(sid, i)) != NULL)
1702                     print_to_screen("            %u\n", *subauth);
1703                 }
1704 #endif
1705             }
1706           else if ((!memcmp(Attribute, "userAccountControl", 
1707                             strlen("userAccountControl"))) ||
1708                    (!memcmp(Attribute, "sAMAccountType", 
1709                             strlen("sAmAccountType"))))
1710             {
1711               intValue = atoi(*Ptr);
1712               print_to_screen("     %20s : %ld\n",Attribute, intValue);
1713               if (!memcmp(Attribute, "userAccountControl", 
1714                           strlen("userAccountControl")))
1715                 {
1716                   if (intValue & UF_ACCOUNTDISABLE)
1717                     print_to_screen("     %20s :    %s\n", 
1718                                     "", "Account disabled");
1719                   else
1720                     print_to_screen("     %20s :    %s\n", 
1721                                     "", "Account active");
1722                   if (intValue & UF_HOMEDIR_REQUIRED)
1723                     print_to_screen("     %20s :    %s\n", 
1724                                     "", "Home directory required");
1725                   if (intValue & UF_LOCKOUT)
1726                     print_to_screen("     %20s :    %s\n", 
1727                                     "", "Account locked out");
1728                   if (intValue & UF_PASSWD_NOTREQD)
1729                     print_to_screen("     %20s :    %s\n", 
1730                                     "", "No password required");
1731                   if (intValue & UF_PASSWD_CANT_CHANGE)
1732                     print_to_screen("     %20s :    %s\n",
1733                                     "", "Cannot change password");
1734                   if (intValue & UF_TEMP_DUPLICATE_ACCOUNT)
1735                     print_to_screen("     %20s :    %s\n", 
1736                                     "", "Temp duplicate account");
1737                   if (intValue & UF_NORMAL_ACCOUNT)
1738                     print_to_screen("     %20s :    %s\n", 
1739                                     "", "Normal account");
1740                   if (intValue & UF_INTERDOMAIN_TRUST_ACCOUNT)
1741                     print_to_screen("     %20s :    %s\n", 
1742                                     "", "Interdomain trust account");
1743                   if (intValue & UF_WORKSTATION_TRUST_ACCOUNT)
1744                     print_to_screen("     %20s :    %s\n", 
1745                                     "", "Workstation trust account");
1746                   if (intValue & UF_SERVER_TRUST_ACCOUNT)
1747                     print_to_screen("     %20s :    %s\n", 
1748                                     "", "Server trust account");
1749                 }
1750             }
1751           else
1752             {
1753               print_to_screen("     %20s : %s\n",Attribute, *Ptr);
1754             }
1755 #endif /*LDAP_DEBUG*/
1756         }
1757       if (str_value != NULL)
1758         ldap_value_free(str_value);
1759       if (ber_value != NULL)
1760         ldap_value_free_len(ber_value);
1761     }
1762   (*linklist_current) = linklist_previous;
1763   return(0);
1764 }
1765
1766 int moira_connect(void)
1767 {
1768   long    rc;
1769   char    HostName[64];
1770
1771   if (!mr_connections++)
1772     {
1773 #ifdef _WIN32
1774       memset(HostName, '\0', sizeof(HostName));
1775       strcpy(HostName, "ttsp");
1776       rc = mr_connect_cl(HostName, "winad.incr", QUERY_VERSION, 1);
1777 /*det
1778       rc = mr_connect(HostName);
1779 */
1780 #else
1781       struct utsname uts;
1782       uname(&uts);
1783       rc = mr_connect_cl(uts.nodename, "winad.incr", QUERY_VERSION, 1);
1784 /*
1785       rc = mr_connect(uts.nodename);
1786 */
1787 #endif /*WIN32*/
1788 /*det
1789       if (!rc)
1790         rc = mr_krb5_auth("winad.incr");
1791 */
1792       return rc;
1793     }
1794   return 0;
1795 }
1796
1797 int check_winad(void)
1798 {
1799   int i;
1800   
1801   for (i = 0; file_exists(STOP_FILE); i++)
1802     {
1803       if (i > 30)
1804         {
1805           critical_alert("AD incremental",
1806                          "WINAD incremental failed (%s exists): %s",
1807                          STOP_FILE, tbl_buf);
1808           return(1);
1809         }
1810       sleep(60);
1811     }
1812   return(0);
1813 }
1814
1815 int moira_disconnect(void)
1816 {
1817
1818   if (!--mr_connections)
1819     {
1820       mr_disconnect();
1821     }
1822   return 0;
1823 }
1824
1825 void get_distinguished_name(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
1826                             char *distinguished_name)
1827 {
1828   char    *CName;
1829
1830   CName = ldap_get_dn(ldap_handle, ldap_entry);
1831   if (CName == NULL)
1832     return;
1833   strcpy(distinguished_name, CName);
1834   ldap_memfree(CName);
1835 }
1836
1837 int linklist_create_entry(char *attribute, char *value, 
1838                           LK_ENTRY **linklist_entry)
1839 {
1840   (*linklist_entry) = calloc(1, sizeof(LK_ENTRY));
1841   if (!(*linklist_entry))
1842     {
1843       return(1);
1844     }
1845   memset((*linklist_entry), '\0', sizeof(LK_ENTRY));
1846   (*linklist_entry)->attribute = calloc(1, strlen(attribute) + 1);
1847   memset((*linklist_entry)->attribute, '\0', strlen(attribute) + 1);
1848   strcpy((*linklist_entry)->attribute, attribute);
1849   (*linklist_entry)->value = calloc(1, strlen(value) + 1);
1850   memset((*linklist_entry)->value, '\0', strlen(value) + 1);
1851   strcpy((*linklist_entry)->value, value);
1852   (*linklist_entry)->length = strlen(value);
1853   (*linklist_entry)->next = NULL;
1854   return(0);
1855 }
1856
1857 void print_to_screen(const char *fmt, ...)
1858 {
1859   va_list pvar;
1860
1861   va_start(pvar, fmt);
1862   vfprintf(stderr, fmt, pvar);
1863   fflush(stderr);
1864   va_end(pvar);
1865 }
1866
1867 int get_group_membership(char *group_membership, char *group_ou, 
1868                          int *security_flag, char **av)
1869 {
1870   int  maillist_flag;
1871   int  group_flag;
1872
1873   maillist_flag = atoi(av[L_MAILLIST]);
1874   group_flag = atoi(av[L_GROUP]);
1875   if (security_flag != NULL)
1876     (*security_flag) = 0;
1877
1878   if ((maillist_flag) && (group_flag))
1879     {
1880       if (group_membership != NULL)
1881         group_membership[0] = 'B';
1882       if (security_flag != NULL)
1883         (*security_flag) = 1;
1884       if (group_ou != NULL)
1885         strcpy(group_ou, group_ou_both);
1886     }
1887   else if ((!maillist_flag) && (group_flag))
1888     {
1889       if (group_membership != NULL)
1890         group_membership[0] = 'S';
1891       if (security_flag != NULL)
1892         (*security_flag) = 1;
1893       if (group_ou != NULL)
1894         strcpy(group_ou, group_ou_security);
1895     }
1896   else if ((maillist_flag) && (!group_flag))
1897     {
1898       if (group_membership != NULL)
1899         group_membership[0] = 'D';
1900       if (group_ou != NULL)
1901         strcpy(group_ou, group_ou_distribution);
1902     }
1903   else
1904     {
1905       if (group_membership != NULL)
1906         group_membership[0] = 'N';
1907       if (group_ou != NULL)
1908         strcpy(group_ou, group_ou_neither);
1909     }
1910   return(0);
1911 }
1912
1913 int group_rename(LDAP *ldap_handle, char *dn_path, 
1914                  char *before_group_name, char *before_group_membership, 
1915                  char *before_group_ou, int before_security_flag, char *before_desc,
1916                  char *after_group_name, char *after_group_membership, 
1917                  char *after_group_ou, int after_security_flag, char *after_desc,
1918                  char *MoiraId, char *filter)
1919 {
1920   LDAPMod   *mods[20];
1921   char      old_dn[512];
1922   char      new_dn[512];
1923   char      new_dn_path[512];
1924   char      sam_name[256];
1925   char      *attr_array[3];
1926   char      *mitMoiraId_v[] = {NULL, NULL};
1927   char      *name_v[] = {NULL, NULL};
1928   char      *samAccountName_v[] = {NULL, NULL};
1929   char      *groupTypeControl_v[] = {NULL, NULL};
1930   u_int     groupTypeControl = ADS_GROUP_TYPE_GLOBAL_GROUP;
1931   char      groupTypeControlStr[80];
1932   int       n;
1933   int       i;
1934   int       rc;
1935   LK_ENTRY  *group_base;
1936   int       group_count;
1937
1938   if (!check_string(before_group_name))
1939     {
1940       com_err(whoami, 0, "Unable to process invalid LDAP list name %s", before_group_name);
1941       return(AD_INVALID_NAME);
1942     }
1943   if (!check_string(after_group_name))
1944     {
1945       com_err(whoami, 0, "Unable to process invalid LDAP list name %s", after_group_name);
1946       return(AD_INVALID_NAME);
1947     }
1948
1949   group_count = 0;
1950   group_base = NULL;
1951   if (rc = ad_get_group(ldap_handle, dn_path, before_group_name, 
1952                         before_group_membership, 
1953                         MoiraId, "distinguishedName", &group_base, 
1954                         &group_count, filter))
1955     return(rc);
1956
1957   if (group_count == 0)
1958     {
1959       return(AD_NO_GROUPS_FOUND);
1960     }
1961   if (group_count != 1)
1962     {
1963       com_err(whoami, 0,
1964               "Unable to process multiple groups with MoiraId = %s exist in the AD",
1965               MoiraId);
1966       return(AD_MULTIPLE_GROUPS_FOUND);
1967     }
1968   strcpy(old_dn, group_base->value);
1969
1970   linklist_free(group_base);
1971   group_base = NULL;
1972   group_count = 0;
1973   attr_array[0] = "sAMAccountName";
1974   attr_array[1] = NULL;
1975   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
1976                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
1977     {
1978       com_err(whoami, 0, "Unable to get list %s dn : %s",
1979               after_group_name, ldap_err2string(rc));
1980       return(rc);
1981     }
1982   if (group_count != 1)
1983     {
1984       com_err(whoami, 0,
1985               "Unable to get sAMAccountName for group %s", 
1986               before_group_name);
1987       return(AD_LDAP_FAILURE);
1988     }
1989
1990   strcpy(sam_name, group_base->value);
1991   linklist_free(group_base);
1992   group_base = NULL;
1993   group_count = 0;
1994
1995   sprintf(new_dn_path, "%s,%s", after_group_ou, dn_path);
1996   sprintf(new_dn, "cn=%s", after_group_name);
1997   if ((rc = ldap_rename_s(ldap_handle, old_dn, new_dn, new_dn_path,
1998                           TRUE, NULL, NULL)) != LDAP_SUCCESS)
1999     {
2000       com_err(whoami, 0, "Unable to rename list from %s to %s : %s",
2001               before_group_name, after_group_name, ldap_err2string(rc));
2002       return(rc);
2003     }
2004
2005   name_v[0] = after_group_name;
2006   if (!strncmp(&sam_name[strlen(sam_name) - strlen("_group")], "_group", strlen("_group")))
2007     {
2008       sprintf(sam_name, "%s_group", after_group_name);
2009     }
2010   else
2011     {
2012       com_err(whoami, 0, "Unable to rename list from %s to %s : sAMAccountName not found",
2013               before_group_name, after_group_name);
2014       return(rc);
2015     }
2016   samAccountName_v[0] = sam_name;
2017   if (after_security_flag)
2018     groupTypeControl |= ADS_GROUP_TYPE_SECURITY_ENABLED;
2019   sprintf(groupTypeControlStr, "%ld", groupTypeControl);
2020   groupTypeControl_v[0] = groupTypeControlStr;
2021   mitMoiraId_v[0] = MoiraId;
2022
2023   sprintf(new_dn, "cn=%s,%s,%s", after_group_name, after_group_ou, dn_path);
2024   rc = attribute_update(ldap_handle, new_dn, after_desc, "description", after_group_name);
2025   n = 0;
2026   ADD_ATTR("samAccountName", samAccountName_v, LDAP_MOD_REPLACE);
2027   ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
2028   ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
2029   ADD_ATTR("groupType", groupTypeControl_v, LDAP_MOD_REPLACE);
2030   mods[n] = NULL;
2031   if ((rc = ldap_modify_s(ldap_handle, new_dn, mods)) != LDAP_SUCCESS)
2032     {
2033       com_err(whoami, 0, "Unable to modify list data for %s after renaming: %s",
2034               after_group_name, ldap_err2string(rc));
2035     }
2036   for (i = 0; i < n; i++)
2037     free(mods[i]);
2038   return(rc);
2039 }
2040
2041 int group_create(int ac, char **av, void *ptr)
2042 {
2043   LDAPMod *mods[20];
2044   char new_dn[256];
2045   char group_ou[256];
2046   char new_group_name[256];
2047   char sam_group_name[256];
2048   char cn_group_name[256];
2049   char *cn_v[] = {NULL, NULL};
2050   char *objectClass_v[] = {"top", "group", NULL};
2051   char info[256];
2052   char *samAccountName_v[] = {NULL, NULL};
2053   char *altSecurityIdentities_v[] = {NULL, NULL};
2054   char *member_v[] = {NULL, NULL};
2055   char *name_v[] = {NULL, NULL};
2056   char *desc_v[] = {NULL, NULL};
2057   char *info_v[] = {NULL, NULL};
2058   char *mitMoiraId_v[] = {NULL, NULL};
2059   char *groupTypeControl_v[] = {NULL, NULL};
2060   char groupTypeControlStr[80];
2061   char group_membership[1];
2062   int  i;
2063   int  security_flag;
2064   u_int groupTypeControl = ADS_GROUP_TYPE_GLOBAL_GROUP;
2065   int  n;
2066   int  rc;
2067   int  updateGroup;
2068   char **call_args;
2069
2070   call_args = ptr;
2071
2072   if (!check_string(av[L_NAME]))
2073     {
2074       com_err(whoami, 0, "Unable to process invalid LDAP list name %s", av[L_NAME]);
2075       return(AD_INVALID_NAME);
2076     }
2077
2078   updateGroup = (int)call_args[4];
2079   memset(group_ou, 0, sizeof(group_ou));
2080   memset(group_membership, 0, sizeof(group_membership));
2081   security_flag = 0;
2082   get_group_membership(group_membership, group_ou, &security_flag, av);
2083   strcpy(new_group_name, av[L_NAME]);
2084   sprintf(new_dn, "cn=%s,%s,%s", new_group_name, group_ou, call_args[1]);
2085   if (security_flag)
2086     groupTypeControl |= ADS_GROUP_TYPE_SECURITY_ENABLED;
2087   
2088   sprintf(sam_group_name, "%s_group", av[L_NAME]);
2089
2090   if (!updateGroup)
2091     {
2092
2093       sprintf(groupTypeControlStr, "%ld", groupTypeControl);
2094       groupTypeControl_v[0] = groupTypeControlStr;
2095
2096       strcpy(cn_group_name, av[L_NAME]);
2097
2098       samAccountName_v[0] = sam_group_name;
2099       name_v[0] = new_group_name;
2100       cn_v[0] = new_group_name;
2101
2102       n = 0;
2103       ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
2104       ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2105       ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
2106       ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2107       ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2108       if (strlen(av[L_DESC]) != 0)
2109         {
2110           desc_v[0] = av[L_DESC];
2111           ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2112         }
2113       ADD_ATTR("groupType", groupTypeControl_v, LDAP_MOD_ADD);
2114       if (strlen(av[L_ACE_NAME]) != 0)
2115         {
2116           sprintf(info, "The Administrator of this list is: %s", av[L_ACE_NAME]);
2117           info_v[0] = info;
2118           ADD_ATTR("info", info_v, LDAP_MOD_ADD);
2119         }
2120       if (strlen(call_args[5]) != 0)
2121         {
2122           mitMoiraId_v[0] = call_args[5];
2123           ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_ADD);
2124         }
2125       mods[n] = NULL;
2126
2127       rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
2128
2129       for (i = 0; i < n; i++)
2130         free(mods[i]);
2131       if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2132         {
2133           com_err(whoami, 0, "Unable to create list %s in AD : %s",
2134                   av[L_NAME], ldap_err2string(rc));
2135           callback_rc = rc;
2136           return(rc);
2137         }
2138     }
2139   if ((rc == LDAP_ALREADY_EXISTS) || (updateGroup))
2140     {
2141       rc = attribute_update((LDAP *)call_args[0], new_dn, av[L_DESC], "description", av[L_NAME]);
2142       sprintf(info, "The Administrator of this list is: %s", av[L_ACE_NAME]);
2143       rc = attribute_update((LDAP *)call_args[0], new_dn, info, "info", av[L_NAME]);
2144       n = 0;
2145       if (strlen(call_args[5]) != 0)
2146         {
2147           mitMoiraId_v[0] = call_args[5];
2148           ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
2149         }
2150       if (!(atoi(av[L_ACTIVE])))
2151         {
2152           member_v[0] = NULL;
2153           ADD_ATTR("member", member_v, LDAP_MOD_REPLACE);
2154         }
2155       mods[n] = NULL;
2156       rc = LDAP_SUCCESS;
2157       if (n != 0)
2158         {
2159           rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
2160           for (i = 0; i < n; i++)
2161               free(mods[i]);
2162           if (rc != LDAP_SUCCESS)
2163             {
2164               com_err(whoami, 0, "Unable to update list %s in AD : %s",
2165                       av[L_NAME], ldap_err2string(rc));
2166               callback_rc = rc;
2167               return(rc);
2168             }
2169         }
2170     }
2171
2172   ProcessGroupSecurity((LDAP *)call_args[0], call_args[1], av[L_NAME], 
2173                        atoi(av[L_HIDDEN]),  av[L_ACE_TYPE], av[L_ACE_NAME]);
2174
2175   return(LDAP_SUCCESS);
2176 }
2177
2178 int ProcessGroupSecurity(LDAP *ldap_handle, char *dn_path, char *TargetGroupName, 
2179                          int HiddenGroup, char *AceType, char *AceName)
2180 {
2181   char          filter_exp[1024];
2182   char          *attr_array[5];
2183   char          search_path[512];
2184   char          root_ou[128];
2185   char          TemplateDn[512];
2186   char          TemplateSamName[128];
2187   char          TargetDn[512];
2188   char          TargetSamName[128];
2189   char          AceSamAccountName[128];
2190   char          AceDn[256];
2191   unsigned char AceSid[128];
2192   unsigned char UserTemplateSid[128];
2193   char          acBERBuf[N_SD_BER_BYTES];
2194   char          GroupSecurityTemplate[256];
2195   int           AceSidCount;
2196   int           UserTemplateSidCount;
2197   int           group_count;
2198   int           n;
2199   int           i;
2200   int           rc;
2201   int           nVal;
2202   ULONG         dwInfo;
2203   int           array_count = 0;
2204   LDAPMod       *mods[20];
2205   LK_ENTRY      *group_base;
2206   LDAP_BERVAL   **ppsValues;
2207   LDAPControl sControl = {"1.2.840.113556.1.4.801",
2208                           { N_SD_BER_BYTES, acBERBuf },
2209                           TRUE
2210                          };
2211   LDAPControl *apsServerControls[] = {&sControl, NULL};
2212   LDAPMessage *psMsg;
2213
2214   dwInfo = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;
2215   BEREncodeSecurityBits(dwInfo, acBERBuf);
2216
2217   sprintf(search_path, "%s,%s", group_ou_root, dn_path);
2218   sprintf(filter_exp, "(sAMAccountName=%s_group)", TargetGroupName);
2219   attr_array[0] = "sAMAccountName";
2220   attr_array[1] = NULL;
2221   group_count = 0;
2222   group_base = NULL;
2223   if ((rc = linklist_build(ldap_handle, search_path, filter_exp, attr_array, 
2224                                &group_base, &group_count, LDAP_SCOPE_SUBTREE) != 0))
2225     return(1);
2226   if (group_count != 1)
2227     {
2228       linklist_free(group_base);
2229       return(1);
2230     }
2231   strcpy(TargetDn, group_base->dn);
2232   strcpy(TargetSamName, group_base->value);
2233   linklist_free(group_base);
2234   group_base = NULL;
2235   group_count = 0;
2236
2237   UserTemplateSidCount = 0;
2238   memset(UserTemplateSid, '\0', sizeof(UserTemplateSid));
2239   memset(AceSamAccountName, '\0', sizeof(AceSamAccountName));
2240   memset(AceSid, '\0', sizeof(AceSid));
2241   AceSidCount = 0;
2242   group_base = NULL;
2243   group_count = 0;
2244   if (strlen(AceName) != 0)
2245     {
2246       if (!strcmp(AceType, "LIST"))
2247         {
2248           sprintf(AceSamAccountName, "%s_group", AceName);
2249           strcpy(root_ou, group_ou_root);
2250         }
2251       else if (!strcmp(AceType, "USER"))
2252         {
2253           sprintf(AceSamAccountName, "%s", AceName);
2254           strcpy(root_ou, user_ou);
2255         }
2256       if (strlen(AceSamAccountName) != 0)
2257         {
2258           sprintf(search_path, "%s", dn_path);
2259           sprintf(filter_exp, "(sAMAccountName=%s)", AceSamAccountName);
2260           attr_array[0] = "objectSid";
2261           attr_array[1] = NULL;
2262           group_count = 0;
2263           group_base = NULL;
2264           if ((rc = linklist_build(ldap_handle, search_path, filter_exp, attr_array, 
2265                                    &group_base, &group_count, LDAP_SCOPE_SUBTREE) != 0))
2266             return(1);
2267           if (group_count == 1)
2268             {
2269               strcpy(AceDn, group_base->dn);
2270               AceSidCount = group_base->length;
2271               memcpy(AceSid, group_base->value, AceSidCount);
2272             }
2273           linklist_free(group_base);
2274           group_base = NULL;
2275           group_count = 0;
2276         }
2277     }
2278   if (AceSidCount == 0)
2279     {
2280       com_err(whoami, 0, "Group %s: Administrator: %s, Type: %s - does not have an AD SID.", TargetGroupName, AceName, AceType);
2281       com_err(whoami, 0, "   Non-admin security group template will be used.");
2282     }
2283   else
2284     {
2285       sprintf(search_path, "%s,%s", security_template_ou, dn_path);
2286       sprintf(filter_exp, "(sAMAccountName=%s)", "UserTemplate.u");
2287       attr_array[0] = "objectSid";
2288       attr_array[1] = NULL;
2289
2290       group_count = 0;
2291       group_base = NULL;
2292       if ((rc = linklist_build(ldap_handle, search_path, filter_exp, attr_array, 
2293                                    &group_base, &group_count, LDAP_SCOPE_SUBTREE) != 0))
2294         return(1);
2295       if ((rc != 0) || (group_count != 1))
2296         {
2297           com_err(whoami, 0, "Unable to process user security template: %s", "UserTemplate");
2298           AceSidCount = 0;
2299         }
2300       else
2301         {
2302           UserTemplateSidCount = group_base->length;
2303           memcpy(UserTemplateSid, group_base->value, UserTemplateSidCount);
2304         }
2305       linklist_free(group_base);
2306       group_base = NULL;
2307       group_count = 0;
2308     }
2309
2310   if (HiddenGroup)
2311     {
2312       if (AceSidCount == 0)
2313         {
2314           strcpy(GroupSecurityTemplate, HIDDEN_GROUP);
2315           sprintf(filter_exp, "(sAMAccountName=%s)", HIDDEN_GROUP);
2316         }
2317       else
2318         {
2319           strcpy(GroupSecurityTemplate, HIDDEN_GROUP_WITH_ADMIN);
2320           sprintf(filter_exp, "(sAMAccountName=%s)", HIDDEN_GROUP_WITH_ADMIN);
2321         }
2322     }
2323   else
2324     {
2325       if (AceSidCount == 0)
2326         {
2327           strcpy(GroupSecurityTemplate, NOT_HIDDEN_GROUP);
2328           sprintf(filter_exp, "(sAMAccountName=%s)", NOT_HIDDEN_GROUP);
2329         }
2330       else
2331         {
2332           strcpy(GroupSecurityTemplate, NOT_HIDDEN_GROUP_WITH_ADMIN);
2333           sprintf(filter_exp, "(sAMAccountName=%s)", NOT_HIDDEN_GROUP_WITH_ADMIN);
2334         }
2335     }
2336
2337   sprintf(search_path, "%s,%s", security_template_ou, dn_path);
2338   attr_array[0] = "sAMAccountName";
2339   attr_array[1] = NULL;
2340   group_count = 0;
2341   group_base = NULL;
2342   if ((rc = linklist_build(ldap_handle, search_path, filter_exp, attr_array, 
2343                                &group_base, &group_count, LDAP_SCOPE_SUBTREE) != 0))
2344     return(1);
2345   if (group_count != 1)
2346     {
2347       linklist_free(group_base);
2348       com_err(whoami, 0, "Unable to process group security template: %s - security not set", GroupSecurityTemplate);
2349       return(1);
2350     }
2351   strcpy(TemplateDn, group_base->dn);
2352   strcpy(TemplateSamName, group_base->value);
2353   linklist_free(group_base);
2354   group_base = NULL;
2355   group_count = 0;
2356
2357   sprintf(filter_exp, "(sAMAccountName=%s)", TemplateSamName);
2358   rc = ldap_search_ext_s(ldap_handle,
2359                          TemplateDn,
2360                          LDAP_SCOPE_SUBTREE,
2361                          filter_exp,
2362                          NULL,
2363                          0,
2364                          apsServerControls,
2365                          NULL,
2366                          NULL,
2367                          0,
2368                          &psMsg);
2369
2370   if ((psMsg = ldap_first_entry(ldap_handle, psMsg)) == NULL)
2371     {
2372       com_err(whoami, 0, "Unable to find group security template: %s - security not set", GroupSecurityTemplate);
2373       return(1);
2374     }
2375   ppsValues = ldap_get_values_len(ldap_handle, psMsg, "ntSecurityDescriptor");
2376   if (ppsValues == NULL)
2377     {
2378       com_err(whoami, 0, "Unable to find group security descriptor for group %s - security not set", GroupSecurityTemplate);
2379       return(1);
2380     }
2381
2382   if (AceSidCount != 0)
2383     {
2384       for (nVal = 0; ppsValues[nVal] != NULL; nVal++)
2385         {
2386           for (i = 0; i < (int)(ppsValues[nVal]->bv_len - UserTemplateSidCount); i++)
2387             {
2388               if (!memcmp(&ppsValues[nVal]->bv_val[i], UserTemplateSid, UserTemplateSidCount))
2389                 {
2390                   memcpy(&ppsValues[nVal]->bv_val[i], AceSid, AceSidCount);
2391                   break;
2392                 }
2393             }
2394         }
2395     }
2396
2397   n = 0;
2398   ADD_ATTR("ntSecurityDescriptor", (char **)ppsValues, LDAP_MOD_REPLACE | LDAP_MOD_BVALUES);
2399   mods[n] = NULL;
2400
2401   rc = ldap_modify_s(ldap_handle, TargetDn, mods);
2402   for (i = 0; i < n; i++)
2403     free(mods[i]);
2404   ldap_value_free_len(ppsValues);
2405   ldap_msgfree(psMsg);
2406   if (rc != LDAP_SUCCESS)
2407     {
2408       com_err(whoami, 0, "Unable to set security settings for group %s : %s",
2409               TargetGroupName, ldap_err2string(rc));
2410       if (AceSidCount != 0)
2411         {
2412           com_err(whoami, 0, "Trying to set security for group %s without admin.",
2413                   TargetGroupName);
2414           if (rc = ProcessGroupSecurity(ldap_handle, dn_path, TargetGroupName, 
2415                                         HiddenGroup, "", ""))
2416             {
2417               com_err(whoami, 0, "Unable to set security for group %s.",
2418                       TargetGroupName);
2419               return(rc);
2420             }
2421         }
2422       return(rc);
2423     }
2424   return(rc);
2425 }
2426
2427 int group_delete(LDAP *ldap_handle, char *dn_path, char *group_name, 
2428                  char *group_membership, char *MoiraId)
2429 {
2430   LK_ENTRY  *group_base;
2431   char      temp[512];
2432   char      filter[128];
2433   int       group_count;
2434   int       rc;
2435
2436   if (!check_string(group_name))
2437     {
2438       com_err(whoami, 0, "Unable to process invalid LDAP list name %s", group_name);
2439       return(AD_INVALID_NAME);
2440     }
2441
2442   memset(filter, '\0', sizeof(filter));
2443   group_count = 0;
2444   group_base = NULL;
2445   sprintf(temp, "%s,%s", group_ou_root, dn_path);
2446   if (rc = ad_get_group(ldap_handle, temp, group_name, 
2447                         group_membership, MoiraId, 
2448                         "distinguishedName", &group_base, 
2449                         &group_count, filter))
2450     return(rc);
2451
2452   if (group_count == 1)
2453     {
2454       if ((rc = ldap_delete_s(ldap_handle, group_base->value)) != LDAP_SUCCESS)
2455         {
2456           linklist_free(group_base);
2457           com_err(whoami, 0, "Unable to delete list %s from AD : %s",
2458                   group_name, ldap_err2string(rc));
2459           return(rc);
2460         }
2461       linklist_free(group_base);
2462     }
2463   else
2464     {
2465       linklist_free(group_base);
2466       com_err(whoami, 0, "Unable to find list %s in AD.", group_name);
2467       return(AD_NO_GROUPS_FOUND);
2468     }
2469
2470   return(0);
2471 }
2472
2473 int BEREncodeSecurityBits(ULONG uBits, char *pBuffer)
2474 {
2475     *pBuffer++ = 0x30;
2476     *pBuffer++ = 0x03;
2477     *pBuffer++ = 0x02;
2478     *pBuffer++ = 0x00;
2479     return(N_SD_BER_BYTES);
2480 }
2481
2482 int process_lists(int ac, char **av, void *ptr)
2483 {
2484   int   rc;
2485   int   security_flag;
2486   char  group_ou[256];
2487   char  group_membership[2];
2488   char  **call_args;
2489
2490   call_args = ptr;
2491
2492   security_flag = 0;
2493   memset(group_ou, '\0', sizeof(group_ou));
2494   memset(group_membership, '\0', sizeof(group_membership));
2495   get_group_membership(group_membership, group_ou, &security_flag, av);
2496   rc = member_add((LDAP *)call_args[0], (char *)call_args[1], av[L_NAME],
2497                   group_ou, group_membership, call_args[2], 
2498                   (char *)call_args[3], "");
2499   return(0);
2500 }
2501
2502 int member_list_build(int ac, char **av, void *ptr)
2503 {
2504   LK_ENTRY  *linklist;
2505   char      temp[1024];
2506   char      **call_args;
2507
2508   call_args = ptr;
2509
2510   strcpy(temp, av[ACE_NAME]);
2511   if (!check_string(temp))
2512     return(0);
2513   if (!strcmp(av[ACE_TYPE], "USER"))
2514     {
2515       if (!((int)call_args[3] & MOIRA_USERS))
2516         return(0);
2517     }
2518   else if (!strcmp(av[ACE_TYPE], "STRING"))
2519     {
2520       if (!((int)call_args[3] & MOIRA_STRINGS))
2521         return(0);
2522       if (contact_create((LDAP *)call_args[0], call_args[1], temp, contact_ou))
2523         return(0);
2524     }
2525   else if (!strcmp(av[ACE_TYPE], "LIST"))
2526     {
2527       if (!((int)call_args[3] & MOIRA_LISTS))
2528         return(0);
2529     }
2530   else if (!strcmp(av[ACE_TYPE], "KERBEROS"))
2531     {
2532       if (!((int)call_args[3] & MOIRA_KERBEROS))
2533         return(0);
2534       if (contact_create((LDAP *)call_args[0], call_args[1], temp, kerberos_ou))
2535         return(0);
2536     }
2537   else
2538     return(0);
2539
2540   linklist = member_base;
2541   while (linklist)
2542     {
2543     if (!strcasecmp(temp, linklist->member))
2544       return(0);
2545     linklist = linklist->next;
2546     }
2547   linklist = calloc(1, sizeof(LK_ENTRY));
2548   linklist->op = 1;
2549   linklist->dn = NULL;
2550   linklist->list = calloc(1, strlen(call_args[2]) + 1);
2551   strcpy(linklist->list, call_args[2]);
2552   linklist->type = calloc(1, strlen(av[ACE_TYPE]) + 1);
2553   strcpy(linklist->type, av[ACE_TYPE]);
2554   linklist->member = calloc(1, strlen(temp) + 1);
2555   strcpy(linklist->member, temp);
2556   linklist->next = member_base;
2557   member_base = linklist;
2558   return(0);
2559 }
2560
2561 int member_remove(LDAP *ldap_handle, char *dn_path, char *group_name, 
2562                   char *group_ou, char *group_membership, char *user_name,
2563                   char *UserOu, char *MoiraId)
2564 {
2565   char        distinguished_name[1024];
2566   char        *modvalues[2];
2567   char        temp[256];
2568   char        filter[128];
2569   int         group_count;
2570   int         i;
2571   int         n;
2572   LDAPMod     *mods[20];
2573   LK_ENTRY    *group_base;
2574   ULONG       rc;
2575
2576   if (!check_string(group_name))
2577     return(AD_INVALID_NAME);
2578
2579   memset(filter, '\0', sizeof(filter));
2580   group_base = NULL;
2581   group_count = 0;
2582   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
2583                         group_membership, MoiraId, 
2584                         "distinguishedName", &group_base, 
2585                         &group_count, filter))
2586     return(rc);
2587
2588   if (group_count != 1)
2589     {
2590       com_err(whoami, 0, "Unable to find list %s in AD",
2591               group_name);
2592       linklist_free(group_base);
2593       group_base = NULL;
2594       group_count = 0;
2595       goto cleanup;
2596     }
2597   strcpy(distinguished_name, group_base->value);
2598   linklist_free(group_base);
2599   group_base = NULL;
2600   group_count = 0;
2601
2602   sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
2603   modvalues[0] = temp;
2604   modvalues[1] = NULL;
2605
2606   n = 0;
2607   ADD_ATTR("member", modvalues, LDAP_MOD_DELETE);
2608   mods[n] = NULL;
2609   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
2610   for (i = 0; i < n; i++)
2611     free(mods[i]);
2612   if (rc == LDAP_UNWILLING_TO_PERFORM)
2613     rc = LDAP_SUCCESS;
2614   if (rc != LDAP_SUCCESS)
2615     {
2616       com_err(whoami, 0, "Unable to modify list %s members : %s",
2617               group_name, ldap_err2string(rc));
2618       goto cleanup;
2619     }
2620
2621 cleanup:
2622   return(rc);
2623 }
2624
2625 int member_add(LDAP *ldap_handle, char *dn_path, char *group_name, 
2626                char *group_ou, char *group_membership, char *user_name, 
2627                char *UserOu, char *MoiraId)
2628 {
2629   char        distinguished_name[1024];
2630   char        *modvalues[2];
2631   char        temp[256];
2632   char        filter[128];
2633   int         group_count;
2634   int         n;
2635   int         i;
2636   LDAPMod     *mods[20];
2637   LK_ENTRY    *group_base;
2638   ULONG       rc;
2639
2640   if (!check_string(group_name))
2641     return(AD_INVALID_NAME);
2642
2643   rc = 0;
2644   memset(filter, '\0', sizeof(filter));
2645   group_base = NULL;
2646   group_count = 0;
2647   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
2648                         group_membership, MoiraId, 
2649                         "distinguishedName", &group_base, 
2650                         &group_count, filter))
2651     return(rc);
2652
2653   if (group_count != 1)
2654     {
2655       linklist_free(group_base);
2656       group_base = NULL;
2657       group_count = 0;
2658       com_err(whoami, 0, "Unable to find list %s in AD",
2659               group_name);
2660       return(AD_MULTIPLE_GROUPS_FOUND);
2661     }
2662
2663   strcpy(distinguished_name, group_base->value);
2664   linklist_free(group_base);
2665   group_base = NULL;
2666   group_count = 0;
2667
2668   sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
2669   modvalues[0] = temp;
2670   modvalues[1] = NULL;
2671
2672   n = 0;
2673   ADD_ATTR("member", modvalues, LDAP_MOD_ADD);
2674   mods[n] = NULL;
2675   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
2676   if (rc == LDAP_ALREADY_EXISTS)
2677     rc = LDAP_SUCCESS;
2678   if ((!strcmp(UserOu, contact_ou)) || (!strcmp(UserOu, kerberos_ou)))
2679     {
2680       if (rc == LDAP_UNWILLING_TO_PERFORM)
2681         rc = LDAP_SUCCESS;
2682     }
2683   for (i = 0; i < n; i++)
2684     free(mods[i]);
2685   if (rc != LDAP_SUCCESS)
2686     {
2687       com_err(whoami, 0, "Unable to add %s to list %s as a member : %s",
2688               user_name, group_name, ldap_err2string(rc));
2689     }
2690
2691   return(rc);
2692 }
2693
2694 int contact_create(LDAP *ld, char *bind_path, char *user, char *group_ou)
2695 {
2696   LDAPMod *mods[20];
2697   char new_dn[256];
2698   char cn_user_name[256];
2699   char contact_name[256];
2700   char *email_v[] = {NULL, NULL};
2701   char *cn_v[] = {NULL, NULL};
2702   char *contact_v[] = {NULL, NULL};
2703   char *objectClass_v[] = {"top", "person", 
2704                            "organizationalPerson", 
2705                            "contact", NULL};
2706   char *name_v[] = {NULL, NULL};
2707   char *desc_v[] = {NULL, NULL};
2708   int  n;
2709   int  rc;
2710   int  i;
2711
2712   if (!check_string(user))
2713     {
2714       com_err(whoami, 0, "Unable to process invalid LDAP name %s", user);
2715       return(AD_INVALID_NAME);
2716     }
2717   strcpy(contact_name, user);
2718   sprintf(cn_user_name,"CN=%s,%s,%s", contact_name, group_ou, bind_path);
2719   cn_v[0] = cn_user_name;
2720   contact_v[0] = contact_name;
2721   name_v[0] = user;
2722   desc_v[0] = "Auto account created by Moira";
2723   email_v[0] = user;
2724
2725   strcpy(new_dn, cn_user_name);
2726   n = 0;
2727   ADD_ATTR("cn", contact_v, LDAP_MOD_ADD);
2728   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2729   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2730   ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2731   ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2732   if (!strcmp(group_ou, contact_ou))
2733     {
2734       ADD_ATTR("mail", email_v, LDAP_MOD_ADD);
2735     }
2736   mods[n] = NULL;
2737
2738   rc = ldap_add_ext_s(ld, new_dn, mods, NULL, NULL);
2739   for (i = 0; i < n; i++)
2740     free(mods[i]);
2741   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2742     {
2743       n = 0;
2744       ADD_ATTR("cn", contact_v, LDAP_MOD_ADD);
2745       ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2746       ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2747       ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2748       ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2749       mods[n] = NULL;
2750       rc = ldap_add_ext_s(ld, new_dn, mods, NULL, NULL);
2751       for (i = 0; i < n; i++)
2752         free(mods[i]);
2753     }
2754   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2755     {
2756       com_err(whoami, 0, "Unable to create contact %s : %s",
2757               user, ldap_err2string(rc));
2758       return(rc);
2759     }
2760   return(0);
2761 }
2762
2763 int user_update(LDAP *ldap_handle, char *dn_path, char *user_name,
2764                 char *Uid, char *MitId, char *MoiraId, int State,
2765                 char *WinHomeDir, char *WinProfileDir)
2766 {
2767   LDAPMod   *mods[20];
2768   LK_ENTRY  *group_base;
2769   int  group_count;
2770   char distinguished_name[512];
2771   char *mitMoiraId_v[] = {NULL, NULL};
2772   char *uid_v[] = {NULL, NULL};
2773   char *mitid_v[] = {NULL, NULL};
2774   char *homedir_v[] = {NULL, NULL};
2775   char *winProfile_v[] = {NULL, NULL};
2776   char *drives_v[] = {NULL, NULL};
2777   char *userAccountControl_v[] = {NULL, NULL};
2778   char userAccountControlStr[80];
2779   int  n;
2780   int  rc;
2781   int  i;
2782   int  OldUseSFU30;
2783   u_int userAccountControl = UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD | UF_PASSWD_CANT_CHANGE;
2784   char filter[128];
2785   char *attr_array[3];
2786   char temp[256];
2787
2788   if (!check_string(user_name))
2789     {
2790       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", user_name);
2791       return(AD_INVALID_NAME);
2792     }
2793
2794   group_count = 0;
2795   group_base = NULL;
2796
2797   if (strlen(MoiraId) != 0)
2798     {
2799       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
2800       attr_array[0] = "cn";
2801       attr_array[1] = NULL;
2802       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
2803                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
2804         {
2805           com_err(whoami, 0, "Unable to process user %s : %s",
2806                   user_name, ldap_err2string(rc));
2807           return(rc);
2808         }
2809     }
2810   if (group_count != 1)
2811     {
2812       linklist_free(group_base);
2813       group_base = NULL;
2814       group_count = 0;
2815       sprintf(filter, "(sAMAccountName=%s)", user_name);
2816       attr_array[0] = "cn";
2817       attr_array[1] = NULL;
2818       sprintf(temp, "%s,%s", user_ou, dn_path);
2819       if ((rc = linklist_build(ldap_handle, temp, filter, attr_array, 
2820                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
2821         {
2822           com_err(whoami, 0, "Unable to process user %s : %s",
2823                   user_name, ldap_err2string(rc));
2824           return(rc);
2825         }
2826     }
2827
2828   if (group_count != 1)
2829     {
2830       com_err(whoami, 0, "Unable to find user %s in AD",
2831               user_name);
2832       linklist_free(group_base);
2833       return(AD_NO_USER_FOUND);
2834     }
2835   strcpy(distinguished_name, group_base->dn);
2836
2837   linklist_free(group_base);
2838   group_count = 0;
2839
2840   if ((strlen(MitId) != 0) && (MitId[0] == '9'))
2841     rc = attribute_update(ldap_handle, distinguished_name, MitId, "employeeID", user_name);
2842   else
2843     rc = attribute_update(ldap_handle, distinguished_name, "none", "employeeID", user_name);
2844   rc = attribute_update(ldap_handle, distinguished_name, Uid, "uid", user_name);
2845   rc = attribute_update(ldap_handle, distinguished_name, MoiraId, "mitMoiraId", user_name);
2846
2847   n = 0;
2848   uid_v[0] = Uid;
2849   if (!UseSFU30)
2850     {
2851       ADD_ATTR("uidNumber", uid_v, LDAP_MOD_REPLACE);
2852     }
2853   else
2854     {
2855       ADD_ATTR("msSFU30UidNumber", uid_v, LDAP_MOD_REPLACE);
2856     }
2857
2858
2859   if ((State != US_NO_PASSWD) && (State != US_REGISTERED))
2860     userAccountControl |= UF_ACCOUNTDISABLE;
2861   sprintf(userAccountControlStr, "%ld", userAccountControl);
2862   userAccountControl_v[0] = userAccountControlStr;
2863   ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_REPLACE);
2864
2865   n = SetHomeDirectory(ldap_handle, user_name, distinguished_name, WinHomeDir, 
2866                        WinProfileDir, homedir_v, winProfile_v,
2867                        drives_v, mods, LDAP_MOD_REPLACE, n);
2868
2869   mods[n] = NULL;
2870   if ((rc = ldap_modify_s(ldap_handle, distinguished_name, mods)) != LDAP_SUCCESS)
2871     {
2872         OldUseSFU30 = UseSFU30;
2873         SwitchSFU(mods, &UseSFU30, n);
2874         if (OldUseSFU30 != UseSFU30)
2875             rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
2876         if (rc)
2877         {
2878             com_err(whoami, 0, "Unable to modify user data for %s : %s",
2879                 user_name, ldap_err2string(rc));
2880         }
2881     }
2882   for (i = 0; i < n; i++)
2883     free(mods[i]);
2884   return(rc);
2885 }
2886
2887 int user_rename(LDAP *ldap_handle, char *dn_path, char *before_user_name, 
2888                 char *user_name)
2889 {
2890   LDAPMod *mods[20];
2891   char new_dn[256];
2892   char old_dn[256];
2893   char upn[256];
2894   char temp[128];
2895   char *userPrincipalName_v[] = {NULL, NULL};
2896   char *altSecurityIdentities_v[] = {NULL, NULL};
2897   char *name_v[] = {NULL, NULL};
2898   char *samAccountName_v[] = {NULL, NULL};
2899   int  n;
2900   int  rc;
2901   int  i;
2902
2903   if (!check_string(before_user_name))
2904     {
2905       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", before_user_name);
2906       return(AD_INVALID_NAME);
2907     }
2908   if (!check_string(user_name))
2909     {
2910       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", user_name);
2911       return(AD_INVALID_NAME);
2912     }
2913
2914   strcpy(user_name, user_name);
2915   sprintf(old_dn, "cn=%s,%s,%s", before_user_name, user_ou, dn_path);
2916   sprintf(new_dn, "cn=%s", user_name);
2917   if ((rc = ldap_rename_s(ldap_handle, old_dn, new_dn, NULL, TRUE, 
2918                            NULL, NULL)) != LDAP_SUCCESS)
2919     {
2920       com_err(whoami, 0, "Unable to rename user from %s to %s : %s",
2921               before_user_name, user_name, ldap_err2string(rc));
2922       return(rc);
2923     }
2924
2925   name_v[0] = user_name;
2926   sprintf(upn, "%s@%s", user_name, ldap_domain);
2927   userPrincipalName_v[0] = upn;
2928   sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
2929   altSecurityIdentities_v[0] = temp;
2930   samAccountName_v[0] = user_name;
2931
2932   n = 0;
2933   ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_REPLACE);
2934   ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_REPLACE);
2935   ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
2936   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_REPLACE);
2937   mods[n] = NULL;
2938   sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, dn_path);
2939   if ((rc = ldap_modify_s(ldap_handle, new_dn, mods)) != LDAP_SUCCESS)
2940     {
2941       com_err(whoami, 0, "Unable to modify user data for %s after renaming : %s",
2942               user_name, ldap_err2string(rc));
2943     }
2944   for (i = 0; i < n; i++)
2945     free(mods[i]);
2946   return(rc);
2947 }
2948
2949
2950 int user_create(int ac, char **av, void *ptr)
2951 {
2952   LDAPMod *mods[20];
2953   char new_dn[256];
2954   char user_name[256];
2955   char sam_name[256];
2956   char upn[256];
2957   char *cn_v[] = {NULL, NULL};
2958   char *objectClass_v[] = {"top", "person", 
2959                            "organizationalPerson", 
2960                            "user", NULL};
2961
2962   char *samAccountName_v[] = {NULL, NULL};
2963   char *altSecurityIdentities_v[] = {NULL, NULL};
2964   char *mitMoiraId_v[] = {NULL, NULL};
2965   char *name_v[] = {NULL, NULL};
2966   char *desc_v[] = {NULL, NULL};
2967   char *userPrincipalName_v[] = {NULL, NULL};
2968   char *userAccountControl_v[] = {NULL, NULL};
2969   char *uid_v[] = {NULL, NULL};
2970   char *mitid_v[] = {NULL, NULL};
2971   char *homedir_v[] = {NULL, NULL};
2972   char *winProfile_v[] = {NULL, NULL};
2973   char *drives_v[] = {NULL, NULL};
2974   char userAccountControlStr[80];
2975   char temp[128];
2976   u_int userAccountControl = UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD | UF_PASSWD_CANT_CHANGE;
2977   int  n;
2978   int  rc;
2979   int  i;
2980   int  OldUseSFU30;
2981   char **call_args;
2982   char WinHomeDir[1024];
2983   char WinProfileDir[1024];
2984
2985   call_args = ptr;
2986
2987   if (!check_string(av[U_NAME]))
2988     {
2989       callback_rc = AD_INVALID_NAME;
2990       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", av[U_NAME]);
2991       return(AD_INVALID_NAME);
2992     }
2993
2994   memset(WinHomeDir, '\0', sizeof(WinHomeDir));
2995   memset(WinProfileDir, '\0', sizeof(WinProfileDir));
2996   strcpy(WinHomeDir, av[U_WINHOMEDIR]);
2997   strcpy(WinProfileDir, av[U_WINPROFILEDIR]);
2998   strcpy(user_name, av[U_NAME]);
2999   sprintf(upn, "%s@%s", user_name, ldap_domain);
3000   sprintf(sam_name, "%s", av[U_NAME]);
3001   samAccountName_v[0] = sam_name;
3002   if ((atoi(av[U_STATE]) != US_NO_PASSWD) && (atoi(av[U_STATE]) != US_REGISTERED))
3003     userAccountControl |= UF_ACCOUNTDISABLE;
3004   sprintf(userAccountControlStr, "%ld", userAccountControl);
3005   userAccountControl_v[0] = userAccountControlStr;
3006   userPrincipalName_v[0] = upn;
3007
3008   cn_v[0] = user_name;
3009   name_v[0] = user_name;
3010   desc_v[0] = "Auto account created by Moira";
3011   sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
3012   altSecurityIdentities_v[0] = temp;    
3013   sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, call_args[1]);
3014
3015   n = 0;
3016   ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
3017   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
3018   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
3019   ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_ADD);
3020   ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_ADD);
3021   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
3022   ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
3023   ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
3024   if (strlen(call_args[2]) != 0)    
3025     {
3026       mitMoiraId_v[0] = call_args[2];
3027       ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_ADD);
3028     }
3029   ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_ADD);
3030   if (strlen(av[U_UID]) != 0)
3031     {
3032       uid_v[0] = av[U_UID];
3033       ADD_ATTR("uid", uid_v, LDAP_MOD_ADD);
3034       if (!UseSFU30)
3035         {
3036           ADD_ATTR("uidNumber", uid_v, LDAP_MOD_ADD);
3037         }
3038       else
3039         {
3040           ADD_ATTR("msSFU30UidNumber", uid_v, LDAP_MOD_ADD);
3041         }
3042     }
3043   if ((strlen(av[U_MITID]) != 0) && (av[U_MITID][0] == '9'))
3044       mitid_v[0] = av[U_MITID];
3045   else
3046       mitid_v[0] = "none";
3047   ADD_ATTR("employeeID", mitid_v, LDAP_MOD_ADD);
3048
3049   n = SetHomeDirectory((LDAP *)call_args[0], user_name, new_dn, WinHomeDir, 
3050                        WinProfileDir, homedir_v, winProfile_v,
3051                        drives_v, mods, LDAP_MOD_ADD, n);
3052
3053   mods[n] = NULL;
3054
3055   rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
3056   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
3057   {
3058       OldUseSFU30 = UseSFU30;
3059       SwitchSFU(mods, &UseSFU30, n);
3060       if (OldUseSFU30 != UseSFU30)
3061           rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
3062   }
3063
3064   for (i = 0; i < n; i++)
3065     free(mods[i]);
3066   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
3067     {
3068       com_err(whoami, 0, "Unable to create user %s : %s",
3069               user_name, ldap_err2string(rc));
3070       callback_rc = rc;
3071       return(rc);
3072     }
3073   if (rc == LDAP_SUCCESS)
3074     {
3075       if ((rc = set_password(sam_name, "", ldap_domain)) != 0)
3076         {
3077           ad_kdc_disconnect();
3078           tickets_get_k5();
3079           if (!ad_server_connect(default_server, ldap_domain))
3080             {
3081               com_err(whoami, 0, "Unable to set password for user %s : %s",
3082                       user_name, "cannot get changepw ticket from windows domain");
3083             }
3084           else
3085             {
3086               if ((rc = set_password(sam_name, "", ldap_domain)) != 0)
3087                 {
3088                   com_err(whoami, 0, "Unable to set password for user %s : %ld",
3089                           user_name, rc);
3090                 }
3091             }
3092         }
3093     }
3094   return(0);
3095 }
3096
3097 int user_change_status(LDAP *ldap_handle, char *dn_path, 
3098                        char *user_name, char *MoiraId,
3099                        int operation)
3100 {
3101   char      filter[128];
3102   char      *attr_array[3];
3103   char      temp[256];
3104   char      distinguished_name[1024];
3105   char      **modvalues;
3106   char      *mitMoiraId_v[] = {NULL, NULL};
3107   LDAPMod   *mods[20];
3108   LK_ENTRY  *group_base;
3109   int       group_count;
3110   int       rc;
3111   int       i;
3112   int       n;
3113   ULONG     ulongValue;
3114
3115   if (!check_string(user_name))
3116     {
3117       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", user_name);
3118       return(AD_INVALID_NAME);
3119     }
3120
3121   group_count = 0;
3122   group_base = NULL;
3123
3124   if (strlen(MoiraId) != 0)
3125     {
3126       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
3127       attr_array[0] = "UserAccountControl";
3128       attr_array[1] = NULL;
3129       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3130                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3131         {
3132           com_err(whoami, 0, "Unable to process user %s : %s",
3133                   user_name, ldap_err2string(rc));
3134           return(rc);
3135         }
3136     }
3137   if (group_count != 1)
3138     {
3139       linklist_free(group_base);
3140       group_count = 0;
3141       group_base = NULL;
3142       sprintf(filter, "(sAMAccountName=%s)", user_name);
3143       attr_array[0] = "UserAccountControl";
3144       attr_array[1] = NULL;
3145       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3146                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3147         {
3148           com_err(whoami, 0, "Unable to process user %s : %s",
3149                   user_name, ldap_err2string(rc));
3150           return(rc);
3151         }
3152     }
3153
3154   if (group_count != 1)
3155     {
3156       linklist_free(group_base);
3157       com_err(whoami, 0, "Unable to find user %s in AD",
3158               user_name);
3159       return(LDAP_NO_SUCH_OBJECT);
3160     }
3161
3162   strcpy(distinguished_name, group_base->dn);
3163   ulongValue = atoi((*group_base).value);
3164   if (operation == MEMBER_DEACTIVATE)
3165     ulongValue |= UF_ACCOUNTDISABLE;
3166   else    
3167     ulongValue &= ~UF_ACCOUNTDISABLE;
3168   sprintf(temp, "%ld", ulongValue);
3169   if ((rc = construct_newvalues(group_base, group_count, (*group_base).value, 
3170                                 temp, &modvalues, REPLACE)) == 1)
3171     goto cleanup;
3172   linklist_free(group_base);
3173   group_base = NULL;
3174   group_count = 0;
3175   n = 0;
3176   ADD_ATTR("UserAccountControl", modvalues, LDAP_MOD_REPLACE);
3177   if (strlen(MoiraId) != 0)
3178     {
3179     mitMoiraId_v[0] = MoiraId;
3180     ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
3181     }
3182   mods[n] = NULL;
3183   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
3184   for (i = 0; i < n; i++)
3185     free(mods[i]);
3186   free_values(modvalues);
3187   if (rc != LDAP_SUCCESS)
3188     {
3189       com_err(whoami, 0, "Unable to change status of user %s : %s",
3190               user_name, ldap_err2string(rc));
3191     }
3192 cleanup:
3193   return(rc);
3194 }
3195
3196 int user_delete(LDAP *ldap_handle, char *dn_path, 
3197                 char *u_name, char *MoiraId)
3198 {
3199   char      filter[128];
3200   char      *attr_array[3];
3201   char      distinguished_name[1024];
3202   char      user_name[512];
3203   LK_ENTRY  *group_base;
3204   int       group_count;
3205   int       rc;
3206
3207   if (!check_string(u_name))
3208     return(AD_INVALID_NAME);
3209
3210   strcpy(user_name, u_name);
3211   group_count = 0;
3212   group_base = NULL;
3213
3214   if (strlen(MoiraId) != 0)
3215     {
3216       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
3217       attr_array[0] = "name";
3218       attr_array[1] = NULL;
3219       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3220                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3221         {
3222           com_err(whoami, 0, "Unable to process user %s : %s",
3223                   user_name, ldap_err2string(rc));
3224           goto cleanup;
3225         }
3226     }
3227   if (group_count != 1)
3228     {
3229       linklist_free(group_base);
3230       group_count = 0;
3231       group_base = NULL;
3232       sprintf(filter, "(sAMAccountName=%s)", user_name);
3233       attr_array[0] = "name";
3234       attr_array[1] = NULL;
3235       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3236                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3237         {
3238           com_err(whoami, 0, "Unable to process user %s : %s",
3239                   user_name, ldap_err2string(rc));
3240           goto cleanup;
3241         }
3242     }
3243
3244   if (group_count != 1)
3245     {
3246       com_err(whoami, 0, "Unable to find user %s in AD",
3247               user_name);
3248       goto cleanup;
3249     }
3250
3251   strcpy(distinguished_name, group_base->dn);
3252   if (rc = ldap_delete_s(ldap_handle, distinguished_name))
3253     {
3254       com_err(whoami, 0, "Unable to process user %s : %s",
3255               user_name, ldap_err2string(rc));
3256     }
3257
3258 cleanup:
3259   linklist_free(group_base);
3260   return(0);
3261 }
3262
3263 void linklist_free(LK_ENTRY *linklist_base)
3264 {
3265   LK_ENTRY *linklist_previous;
3266
3267   while (linklist_base != NULL)
3268     {
3269       if (linklist_base->dn != NULL)
3270         free(linklist_base->dn);
3271       if (linklist_base->attribute != NULL)
3272         free(linklist_base->attribute);
3273       if (linklist_base->value != NULL)
3274         free(linklist_base->value);
3275       if (linklist_base->member != NULL)
3276         free(linklist_base->member);
3277       if (linklist_base->type != NULL)
3278         free(linklist_base->type);
3279       if (linklist_base->list != NULL)
3280         free(linklist_base->list);
3281       linklist_previous = linklist_base;
3282       linklist_base = linklist_previous->next;
3283       free(linklist_previous);
3284     }
3285 }
3286
3287 void free_values(char **modvalues)
3288 {
3289   int i;
3290
3291   i = 0;
3292   if (modvalues != NULL)
3293     {
3294     while (modvalues[i] != NULL)
3295       {
3296         free(modvalues[i]);
3297         modvalues[i] = NULL;
3298         ++i;
3299       }
3300     free(modvalues);
3301   }
3302 }
3303
3304 static int illegalchars[] = {
3305   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
3306   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
3307   1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, /* SPACE - / */
3308   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 0 - ? */
3309   0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
3310   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* P - _ */
3311   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
3312   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
3313   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3314   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3315   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3316   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3317   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3318   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3319   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3320   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3321 };
3322
3323 int check_string(char *s)
3324 {
3325   char  character;
3326
3327   for (; *s; s++)
3328     {
3329       character = *s;
3330       if (isupper(character))
3331         character = tolower(character);
3332       if (illegalchars[(unsigned) character])
3333         return 0;
3334     }
3335   return 1;
3336 }
3337
3338 int check_container_name(char *s)
3339 {
3340   char  character;
3341
3342   for (; *s; s++)
3343     {
3344       character = *s;
3345       if (isupper(character))
3346         character = tolower(character);
3347
3348           if (character == ' ')
3349                   continue;
3350       if (illegalchars[(unsigned) character])
3351         return 0;
3352     }
3353   return 1;
3354 }
3355
3356 int mr_connect_cl(char *server, char *client, int version, int auth)
3357 {
3358   int   status;
3359   char  *motd;
3360   char  temp[128];
3361
3362   status = mr_connect(server);
3363   if (status)
3364     {
3365       com_err(whoami, status, "while connecting to Moira");
3366       return status;
3367     }
3368
3369   status = mr_motd(&motd);
3370   if (status)
3371     {
3372       mr_disconnect();
3373       com_err(whoami, status, "while checking server status");
3374       return status;
3375     }
3376   if (motd)
3377     {
3378       sprintf(temp, "The Moira server is currently unavailable: %s", motd);
3379       com_err(whoami, status, temp);
3380       mr_disconnect();
3381       return status;
3382     }
3383
3384   status = mr_version(version);
3385   if (status)
3386     {
3387       if (status == MR_UNKNOWN_PROC)
3388         {
3389           if (version > 2)
3390             status = MR_VERSION_HIGH;
3391           else
3392             status = MR_SUCCESS;
3393         }
3394
3395       if (status == MR_VERSION_HIGH)
3396         {
3397           com_err(whoami, 0, "Warning: This client is running newer code than the server.");
3398                   com_err(whoami, 0, "Some operations may not work.");
3399         }
3400       else if (status && status != MR_VERSION_LOW)
3401         {
3402           com_err(whoami, status, "while setting query version number.");
3403           mr_disconnect();
3404           return status;
3405         }
3406     }
3407
3408   if (auth)
3409     {
3410       status = mr_krb5_auth(client);
3411       if (status)
3412         {
3413           com_err(whoami, status, "while authenticating to Moira.");
3414           mr_disconnect();
3415           return status;
3416         }
3417     }
3418
3419   return MR_SUCCESS;
3420 }
3421
3422 void AfsToWinAfs(char* path, char* winPath)
3423 {
3424     char* pathPtr;
3425     char* winPathPtr;
3426     strcpy(winPath, WINAFS);
3427     pathPtr = path + strlen(AFS);
3428     winPathPtr = winPath + strlen(WINAFS);
3429
3430     while (*pathPtr)
3431     {
3432         if (*pathPtr == '/')
3433           *winPathPtr = '\\';
3434         else
3435           *winPathPtr = *pathPtr;
3436
3437         pathPtr++;
3438         winPathPtr++;
3439     }
3440 }
3441
3442 int GetAceInfo(int ac, char **av, void *ptr)
3443 {
3444   char **call_args;
3445   int   security_flag;
3446
3447   call_args = ptr;
3448
3449   strcpy(call_args[0], av[L_ACE_TYPE]);
3450   strcpy(call_args[1], av[L_ACE_NAME]);
3451   security_flag = 0;
3452   get_group_membership(call_args[2], call_args[3], &security_flag, av);
3453   return(LDAP_SUCCESS);
3454
3455 }
3456
3457 int checkADname(LDAP *ldap_handle, char *dn_path, char *Name)
3458 {
3459   char filter[128];
3460   char *attr_array[3];
3461   int  group_count;
3462   int  rc;
3463   LK_ENTRY  *group_base;
3464
3465   group_count = 0;
3466   group_base = NULL;
3467
3468   sprintf(filter, "(sAMAccountName=%s)", Name);
3469   attr_array[0] = "sAMAccountName";
3470   attr_array[1] = NULL;
3471   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3472                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3473     {
3474       com_err(whoami, 0, "Unable to process ACE name %s : %s",
3475               Name, ldap_err2string(rc));
3476       return(1);
3477     }
3478
3479   linklist_free(group_base);
3480   group_base = NULL;
3481   if (group_count == 0)
3482     return(0);
3483   return(1);
3484 }
3485
3486 #define MAX_ACE 7
3487
3488 int ProcessAce(LDAP *ldap_handle, char *dn_path, char *Name, char *Type, int UpdateGroup, int *ProcessGroup)
3489 {
3490   char  *av[2];
3491   char  GroupName[256];
3492   char  *call_args[7];
3493   int   rc;
3494   char  *AceInfo[4];
3495   char  AceType[32];
3496   char  AceName[128];
3497   char  AceMembership[2];
3498   char  AceOu[256];
3499   char  temp[128];
3500
3501   strcpy(GroupName, Name);
3502
3503   if (strcasecmp(Type, "LIST"))
3504     return(1);
3505   while (1)
3506     {
3507       av[0] = GroupName;
3508       AceInfo[0] = AceType;
3509       AceInfo[1] = AceName;
3510       AceInfo[2] = AceMembership;
3511       AceInfo[3] = AceOu;
3512       memset(AceType, '\0', sizeof(AceType));
3513       memset(AceName, '\0', sizeof(AceName));
3514       memset(AceMembership, '\0', sizeof(AceMembership));
3515       memset(AceOu, '\0', sizeof(AceOu));
3516       callback_rc = 0;
3517       if (rc = mr_query("get_list_info", 1, av, GetAceInfo, AceInfo))
3518         {
3519           com_err(whoami, 0, "Unable to get ACE info for list %s : %s", GroupName, error_message(rc));
3520           return(1);
3521         }
3522       if (callback_rc)
3523         {
3524           com_err(whoami, 0, "Unable to get ACE info for list %s", GroupName);
3525           return(1);
3526         }
3527       if ((strcasecmp(AceType, "USER")) && (strcasecmp(AceType, "LIST")))
3528         return(0);
3529       strcpy(temp, AceName);
3530       if (!strcasecmp(AceType, "LIST"))
3531         sprintf(temp, "%s_group", AceName);
3532       if (!UpdateGroup)
3533         {
3534           if (checkADname(ldap_handle, dn_path, temp))
3535             return(0);
3536           (*ProcessGroup) = 1;
3537         }
3538       if (!strcasecmp(AceInfo[0], "LIST"))
3539         {
3540           if (make_new_group(ldap_handle, dn_path, "", AceName, AceOu, AceMembership, 0, UpdateGroup))
3541             return(1);
3542         }
3543       else if (!strcasecmp(AceInfo[0], "USER"))
3544         {
3545           av[0] = AceName;
3546           call_args[0] = (char *)ldap_handle;
3547           call_args[1] = dn_path;
3548           call_args[2] = "";
3549           call_args[3] = NULL;
3550           callback_rc = 0;
3551           if (rc = mr_query("get_user_account_by_login", 1, av, user_create, call_args))
3552             {
3553               com_err(whoami, 0, "Unable to process user ACE %s for group %s.", AceName, Name);
3554               return(1);
3555             }
3556           if (callback_rc)
3557             {
3558               com_err(whoami, 0, "Unable to process user Ace %s for group %s", AceName, Name);
3559               return(1);
3560             }
3561           return(0);
3562         }
3563       else
3564         return(1);
3565       if (!strcasecmp(AceType, "LIST"))
3566         {
3567           if (!strcasecmp(GroupName, AceName))
3568             return(0);
3569         }
3570       strcpy(GroupName, AceName);
3571     }
3572   return(1);
3573 }
3574
3575 int make_new_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
3576                    char *group_name, char *group_ou, char *group_membership, 
3577                    int group_security_flag, int updateGroup)
3578 {
3579   char  *av[3];
3580   char  *call_args[7];
3581   int   rc;
3582
3583   av[0] = group_name;
3584   call_args[0] = (char *)ldap_handle;
3585   call_args[1] = dn_path;
3586   call_args[2] = group_name;
3587   call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
3588   call_args[4] = (char *)updateGroup;
3589   call_args[5] = MoiraId;
3590   call_args[6] = NULL;
3591   callback_rc = 0;
3592   if (rc = mr_query("get_list_info", 1, av, group_create, call_args))
3593     {
3594       moira_disconnect();
3595       com_err(whoami, 0, "Unable to create list %s : %s", group_name, error_message(rc));
3596       return(rc);
3597     }
3598   if (callback_rc)
3599     {
3600       moira_disconnect();
3601       com_err(whoami, 0, "Unable to create list %s", group_name);
3602       return(callback_rc);
3603     }
3604
3605   return(0);
3606 }
3607
3608 int populate_group(LDAP *ldap_handle, char *dn_path, char *group_name, 
3609                    char *group_ou, char *group_membership, 
3610                    int group_security_flag, char *MoiraId)
3611 {
3612   char      *av[3];
3613   char      *call_args[7];
3614   char      *pUserOu;
3615   LK_ENTRY  *ptr;
3616   int       rc;
3617
3618   com_err(whoami, 0, "Populating group %s", group_name);
3619   av[0] = group_name;
3620   call_args[0] = (char *)ldap_handle;
3621   call_args[1] = dn_path;
3622   call_args[2] = group_name;
3623   call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
3624   call_args[4] = NULL;
3625   member_base = NULL;
3626   if (rc = mr_query("get_end_members_of_list", 1, av,
3627                     member_list_build, call_args))
3628     {
3629       com_err(whoami, 0, "Unable to populate list %s : %s", 
3630               group_name, error_message(rc));
3631       return(3);
3632     }
3633   if (member_base != NULL)
3634     {
3635       ptr = member_base;
3636       while (ptr != NULL)
3637         {
3638           if (!strcasecmp(ptr->type, "LIST"))
3639             {
3640               ptr = ptr->next;
3641               continue;
3642             }
3643           pUserOu = user_ou;
3644           if (!strcasecmp(ptr->type, "STRING"))
3645             {
3646               if (contact_create(ldap_handle, dn_path, ptr->member, contact_ou))
3647                 return(3);
3648               pUserOu = contact_ou;
3649             }
3650           else if (!strcasecmp(ptr->type, "KERBEROS"))
3651             {
3652               if (contact_create(ldap_handle, dn_path, ptr->member, kerberos_ou))
3653                 return(3);
3654               pUserOu = kerberos_ou;
3655             }
3656           rc = member_add(ldap_handle, dn_path, group_name,
3657                           group_ou, group_membership, ptr->member, 
3658                           pUserOu, MoiraId);
3659           ptr = ptr->next;
3660         }
3661       linklist_free(member_base);
3662       member_base = NULL;
3663     }
3664   return(0);
3665 }
3666
3667 int process_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
3668                   char *group_name, char *group_ou, char *group_membership, 
3669                   int group_security_flag, int type)
3670 {
3671   char      before_desc[512];
3672   char      before_name[256];
3673   char      before_group_ou[256];
3674   char      before_group_membership[2];
3675   char      distinguishedName[256];
3676   char      ad_distinguishedName[256];
3677   char      filter[128];
3678   char      *attr_array[3];
3679   int       before_security_flag;
3680   int       group_count;
3681   int       rc;
3682   LK_ENTRY  *group_base;
3683   LK_ENTRY  *ptr;
3684   char      ou_both[512];
3685   char      ou_security[512];
3686   char      ou_distribution[512];
3687   char      ou_neither[512];
3688
3689   memset(ad_distinguishedName, '\0', sizeof(ad_distinguishedName));
3690   sprintf(distinguishedName, "CN=%s,%s,%s", group_name, group_ou, dn_path);
3691
3692
3693   memset(filter, '\0', sizeof(filter));
3694   group_base = NULL;
3695   group_count = 0;
3696   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
3697                         "*", MoiraId, 
3698                         "distinguishedName", &group_base, 
3699                         &group_count, filter))
3700     return(rc);
3701
3702   if (type == CHECK_GROUPS)
3703     {
3704       if (group_count == 1)
3705         {
3706           if (!strcasecmp(group_base->value, distinguishedName))
3707             {
3708               linklist_free(group_base);
3709               return(0);
3710             }
3711         }
3712       linklist_free(group_base);
3713       if (group_count == 0)
3714         return(AD_NO_GROUPS_FOUND);
3715       if (group_count == 1)
3716         return(AD_WRONG_GROUP_DN_FOUND);
3717       return(AD_MULTIPLE_GROUPS_FOUND);
3718     }
3719   if (group_count == 0)
3720     {
3721       return(AD_NO_GROUPS_FOUND);
3722     }
3723   if (group_count > 1)
3724     {
3725       ptr = group_base;
3726       while (ptr != NULL)
3727         {
3728           if (!strcasecmp(distinguishedName, ptr->value))
3729             break;
3730           ptr = ptr->next;
3731         }
3732       if (ptr == NULL)
3733         {
3734           com_err(whoami, 0, "%d groups with moira id = %s", group_count, MoiraId);
3735           ptr = group_base;
3736           while (ptr != NULL)
3737             {
3738               com_err(whoami, 0, "%s with moira id = %s", ptr->value, MoiraId);
3739               ptr = ptr->next;
3740             }
3741           linklist_free(group_base);
3742           return(AD_MULTIPLE_GROUPS_FOUND);
3743         }
3744       ptr = group_base;
3745       while (ptr != NULL)
3746         {
3747           if (strcasecmp(distinguishedName, ptr->value))
3748             rc = ldap_delete_s(ldap_handle, ptr->value);
3749           ptr = ptr->next;
3750         }
3751       linklist_free(group_base);
3752       memset(filter, '\0', sizeof(filter));
3753       group_base = NULL;
3754       group_count = 0;
3755       if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
3756                             "*", MoiraId, 
3757                             "distinguishedName", &group_base, 
3758                             &group_count, filter))
3759         return(rc);
3760       if (group_count == 0)
3761         return(AD_NO_GROUPS_FOUND);
3762       if (group_count > 1)
3763         return(AD_MULTIPLE_GROUPS_FOUND);
3764     }
3765
3766   strcpy(ad_distinguishedName, group_base->value);
3767   linklist_free(group_base);
3768   group_base = NULL;
3769   group_count = 0;
3770
3771   attr_array[0] = "sAMAccountName";
3772   attr_array[1] = NULL;
3773   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3774                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3775     {
3776       com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
3777                MoiraId, ldap_err2string(rc));
3778       return(rc);
3779     }
3780   sprintf(filter, "(sAMAccountName=%s)", group_base->value);
3781
3782   if (!strcasecmp(ad_distinguishedName, distinguishedName))
3783     {
3784       linklist_free(group_base);
3785       group_base = NULL;
3786       group_count = 0;
3787       return(0);
3788     }
3789   linklist_free(group_base);
3790   group_base = NULL;
3791   group_count = 0;
3792   memset(ou_both, '\0', sizeof(ou_both));
3793   memset(ou_security, '\0', sizeof(ou_security));
3794   memset(ou_distribution, '\0', sizeof(ou_distribution));
3795   memset(ou_neither, '\0', sizeof(ou_neither));
3796   memset(before_name, '\0', sizeof(before_name));
3797   memset(before_desc, '\0', sizeof(before_desc));
3798   memset(before_group_membership, '\0', sizeof(before_group_membership));
3799   attr_array[0] = "name";
3800   attr_array[1] = NULL;
3801   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3802                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3803     {
3804       com_err(whoami, 0, "Unable to get list name with MoiraId = %s: %s",
3805               MoiraId, ldap_err2string(rc));
3806       return(rc);
3807     }
3808   strcpy(before_name, group_base->value);
3809   linklist_free(group_base);
3810   group_base = NULL;
3811   group_count = 0;
3812   attr_array[0] = "description";
3813   attr_array[1] = NULL;
3814   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3815                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3816     {
3817       com_err(whoami, 0, 
3818               "Unable to get list description with MoiraId = %s: %s",
3819               MoiraId, ldap_err2string(rc));
3820       return(rc);
3821     }
3822   if (group_count != 0)
3823     {
3824       strcpy(before_desc, group_base->value);
3825       linklist_free(group_base);
3826       group_base = NULL;
3827       group_count = 0;
3828     }
3829   change_to_lower_case(ad_distinguishedName);  
3830   strcpy(ou_both, group_ou_both);
3831   change_to_lower_case(ou_both);
3832   strcpy(ou_security, group_ou_security);
3833   change_to_lower_case(ou_security);
3834   strcpy(ou_distribution, group_ou_distribution);
3835   change_to_lower_case(ou_distribution);
3836   strcpy(ou_neither, group_ou_neither);
3837   change_to_lower_case(ou_neither);
3838   if (strstr(ad_distinguishedName, ou_both))
3839     {
3840       strcpy(before_group_ou, group_ou_both);
3841       before_group_membership[0] = 'B';
3842       before_security_flag = 1;
3843     }
3844   else if (strstr(ad_distinguishedName, ou_security))
3845     {
3846       strcpy(before_group_ou, group_ou_security);
3847       before_group_membership[0] = 'S';
3848       before_security_flag = 1;
3849     }
3850   else if (strstr(ad_distinguishedName, ou_distribution))
3851     {
3852       strcpy(before_group_ou, group_ou_distribution);
3853       before_group_membership[0] = 'D';
3854       before_security_flag = 0;
3855     }
3856   else if (strstr(ad_distinguishedName, ou_neither))
3857     {
3858       strcpy(before_group_ou, group_ou_neither);
3859       before_group_membership[0] = 'N';
3860       before_security_flag = 0;
3861     }
3862   else
3863     return(AD_NO_OU_FOUND);
3864   rc = group_rename(ldap_handle, dn_path, before_name, before_group_membership, 
3865                     before_group_ou, before_security_flag, before_desc,
3866                     group_name, group_membership, group_ou, group_security_flag,
3867                     before_desc, MoiraId, filter);
3868   return(rc);
3869 }
3870
3871 void change_to_lower_case(char *ptr)
3872 {
3873   int i;
3874
3875   for (i = 0; i < (int)strlen(ptr); i++)
3876     {
3877       ptr[i] = tolower(ptr[i]);
3878     }
3879 }
3880
3881 int ad_get_group(LDAP *ldap_handle, char *dn_path, 
3882                  char *group_name, char *group_membership, 
3883                  char *MoiraId, char *attribute,
3884                  LK_ENTRY **linklist_base, int *linklist_count,
3885                  char *rFilter)
3886 {
3887   LK_ENTRY  *pPtr;
3888   char  filter[128];
3889   char  *attr_array[3];
3890   int   rc;
3891
3892   (*linklist_base) = NULL;
3893   (*linklist_count) = 0;
3894   if (strlen(rFilter) != 0)
3895     {
3896       strcpy(filter, rFilter);
3897       attr_array[0] = attribute;
3898       attr_array[1] = NULL;
3899       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3900                                linklist_base, linklist_count, LDAP_SCOPE_SUBTREE)) != 0)
3901         {
3902           com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
3903                   MoiraId, ldap_err2string(rc));
3904          return(rc);
3905        }
3906     if ((*linklist_count) == 1)
3907       {
3908         strcpy(rFilter, filter);
3909         return(0);
3910       }
3911     }
3912
3913   linklist_free((*linklist_base));
3914   (*linklist_base) = NULL;
3915   (*linklist_count) = 0;
3916   if (strlen(MoiraId) != 0)
3917     {
3918       sprintf(filter, "(&(objectClass=group)(mitMoiraId=%s))", MoiraId);
3919       attr_array[0] = attribute;
3920       attr_array[1] = NULL;
3921       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3922                                linklist_base, linklist_count, LDAP_SCOPE_SUBTREE)) != 0)
3923         {
3924           com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
3925                   MoiraId, ldap_err2string(rc));
3926          return(rc);
3927        }
3928     }
3929   if ((*linklist_count) > 1)
3930     {
3931       com_err(whoami, 0, "multiple groups with mitMoiraId = %s", MoiraId);
3932       pPtr = (*linklist_base);
3933       while (pPtr)
3934         {
3935           com_err(whoami, 0, "groups %s has mitMoiraId = %s", pPtr->value, MoiraId);
3936           pPtr = pPtr->next;
3937         }
3938       linklist_free((*linklist_base));
3939       (*linklist_base) = NULL;
3940       (*linklist_count) = 0;
3941     }
3942   if ((*linklist_count) == 1)
3943     {
3944       if (!memcmp(&(*linklist_base)->value[3], group_name, strlen(group_name)))
3945         {
3946           strcpy(rFilter, filter);
3947           return(0);
3948         }
3949     }
3950
3951   linklist_free((*linklist_base));
3952   (*linklist_base) = NULL;
3953   (*linklist_count) = 0;
3954   sprintf(filter, "(sAMAccountName=%s_group)", group_name);
3955   attr_array[0] = attribute;
3956   attr_array[1] = NULL;
3957   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3958                            linklist_base, linklist_count, LDAP_SCOPE_SUBTREE)) != 0)
3959     {
3960       com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
3961               MoiraId, ldap_err2string(rc));
3962       return(rc);
3963     }
3964   if ((*linklist_count) == 1)
3965     {
3966       strcpy(rFilter, filter);
3967       return(0);
3968     }
3969
3970   return(0);
3971 }
3972
3973 int check_user(LDAP *ldap_handle, char *dn_path, char *UserName, char *MoiraId)
3974 {
3975   char filter[128];
3976   char *attr_array[3];
3977   char SamAccountName[64];
3978   int  group_count;
3979   int  rc;
3980   LK_ENTRY  *group_base;
3981   LK_ENTRY  *gPtr;
3982
3983   group_count = 0;
3984   group_base = NULL;
3985
3986   if (strlen(MoiraId) != 0)
3987     {
3988       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
3989       attr_array[0] = "sAMAccountName";
3990       attr_array[1] = NULL;
3991       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3992                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3993         {
3994           com_err(whoami, 0, "Unable to process user %s : %s",
3995                   UserName, ldap_err2string(rc));
3996           return(rc);
3997         }
3998       if (group_count > 1)
3999         {
4000           com_err(whoami, 0, "multiple users exist with MoiraId = %s",
4001                   MoiraId);
4002           gPtr = group_base;
4003           while (gPtr)
4004             {
4005               com_err(whoami, 0, "user %s exist with MoiraId = %s",
4006                       gPtr->value, MoiraId);
4007               gPtr = gPtr->next;
4008             }
4009         }
4010     }
4011   if (group_count != 1)
4012     {
4013       linklist_free(group_base);
4014       group_count = 0;
4015       group_base = NULL;
4016       sprintf(filter, "(sAMAccountName=%s)", UserName);
4017       attr_array[0] = "sAMAccountName";
4018       attr_array[1] = NULL;
4019       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4020                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
4021         {
4022           com_err(whoami, 0, "Unable to process user %s : %s",
4023                   UserName, ldap_err2string(rc));
4024           return(rc);
4025         }
4026     }
4027
4028   if (group_count != 1)
4029     {
4030       linklist_free(group_base);
4031       return(AD_NO_USER_FOUND);
4032     }
4033   strcpy(SamAccountName, group_base->value);
4034   linklist_free(group_base);
4035   group_count = 0;
4036   rc = 0;
4037   if (strcmp(SamAccountName, UserName))
4038     {
4039       rc = user_rename(ldap_handle, dn_path, SamAccountName, 
4040                        UserName);
4041     }
4042   return(0);
4043 }
4044
4045 void container_get_dn(char *src, char *dest)
4046 {
4047   char *sPtr;
4048   char *array[20];
4049   char name[256];
4050   int  n;
4051
4052   memset(array, '\0', 20 * sizeof(array[0]));
4053
4054   if (strlen(src) == 0)
4055     return;
4056   strcpy(name, src);
4057   sPtr = name;
4058   n = 0;
4059   array[n] = name;
4060   ++n;
4061   while (*sPtr)
4062     {
4063       if ((*sPtr) == '/')
4064         {
4065           (*sPtr) = '\0';
4066           ++sPtr;
4067           array[n] = sPtr;
4068           ++n;
4069         }
4070       else
4071         ++sPtr;
4072     }
4073   strcpy(dest, "OU=");
4074   while (n != 0)
4075     {
4076       strcat(dest, array[n-1]);
4077       --n;
4078       if (n > 0)
4079         {
4080           strcat(dest, ",OU=");
4081         }
4082     }
4083   return;
4084 }
4085
4086 void container_get_name(char *src, char *dest)
4087 {
4088   char *sPtr;
4089   char *dPtr;
4090
4091   if (strlen(src) == 0)
4092     return;
4093   sPtr = src;
4094   dPtr = src;
4095   while (*sPtr)
4096     {
4097       if ((*sPtr) == '/')
4098         {
4099           dPtr = sPtr;
4100           ++dPtr;
4101         }
4102       ++sPtr;
4103     }
4104   strcpy(dest, dPtr);
4105   return;
4106 }
4107
4108 void container_check(LDAP *ldap_handle, char *dn_path, char *name)
4109 {
4110   char cName[256];
4111   char *av[7];
4112   int  i;
4113   int  rc;
4114
4115   strcpy(cName, name);
4116   for (i = 0; i < (int)strlen(cName); i++)
4117     {
4118       if (cName[i] == '/')
4119         {
4120           cName[i] = '\0';
4121           av[CONTAINER_NAME] = cName;
4122           av[CONTAINER_DESC] = "";
4123           av[CONTAINER_LOCATION] = "";
4124           av[CONTAINER_CONTACT] = "";
4125           av[CONTAINER_TYPE] = "";
4126           av[CONTAINER_ID] = "";
4127           av[CONTAINER_ROWID] = "";
4128           rc = container_create(ldap_handle, dn_path, 7, av);
4129           if (rc == LDAP_SUCCESS)
4130             {
4131               com_err(whoami, 0, "container %s created without a mitMoiraId", cName);
4132             }
4133           cName[i] = '/';
4134         }
4135     }
4136
4137 }
4138
4139 int container_rename(LDAP *ldap_handle, char *dn_path, int beforec, char **before, 
4140                      int afterc, char **after)
4141 {
4142   char      dName[256];
4143   char      cName[256];
4144   char      new_cn[128];
4145   char      new_dn_path[256];
4146   char      temp[256];
4147   char      distinguishedName[256];
4148   char      *pPtr;
4149   int       rc;
4150   int       i;
4151
4152   memset(cName, '\0', sizeof(cName));
4153   container_get_name(after[CONTAINER_NAME], cName);
4154   if (!check_container_name(cName))
4155     {
4156       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", cName);
4157       return(AD_INVALID_NAME);
4158     }
4159
4160   memset(distinguishedName, '\0', sizeof(distinguishedName));
4161   if (rc = container_get_distinguishedName(ldap_handle, dn_path, distinguishedName, beforec, before))
4162     return(rc);
4163   if (strlen(distinguishedName) == 0)
4164     {
4165       rc = container_create(ldap_handle, dn_path, afterc, after);
4166       return(rc);
4167     }
4168
4169   strcpy(temp, after[CONTAINER_NAME]);
4170   pPtr = temp;
4171   for (i = 0; i < (int)strlen(temp); i++)
4172     {
4173       if (temp[i] == '/')
4174         {
4175           pPtr = &temp[i];
4176         }
4177     }
4178   (*pPtr) = '\0';
4179
4180   container_get_dn(temp, dName);
4181   if (strlen(temp) != 0)
4182     sprintf(new_dn_path, "%s,%s", dName, dn_path);
4183   else
4184     sprintf(new_dn_path, "%s", dn_path);
4185   sprintf(new_cn, "OU=%s", cName);
4186
4187   container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
4188
4189   if ((rc = ldap_rename_s(ldap_handle, distinguishedName, new_cn, new_dn_path,
4190                           TRUE, NULL, NULL)) != LDAP_SUCCESS)
4191     {
4192       com_err(whoami, 0, "Unable to rename container from %s to %s : %s",
4193               before[CONTAINER_NAME], after[CONTAINER_NAME], ldap_err2string(rc));
4194       return(rc);
4195     }
4196
4197   memset(dName, '\0', sizeof(dName));
4198   container_get_dn(after[CONTAINER_NAME], dName);
4199   rc = container_adupdate(ldap_handle, dn_path, dName, "", afterc, after);
4200   return(rc);
4201 }
4202
4203 int container_delete(LDAP *ldap_handle, char *dn_path, int count, char **av)
4204 {
4205   char      distinguishedName[256];
4206   int       rc;
4207
4208   memset(distinguishedName, '\0', sizeof(distinguishedName));
4209   if (rc = container_get_distinguishedName(ldap_handle, dn_path, distinguishedName, count, av))
4210     return(rc);
4211   if (strlen(distinguishedName) == 0)
4212     return(0);
4213   if ((rc = ldap_delete_s(ldap_handle, distinguishedName)) != LDAP_SUCCESS)
4214     {
4215       if (rc == LDAP_NOT_ALLOWED_ON_NONLEAF)
4216         container_move_objects(ldap_handle, dn_path, distinguishedName);
4217       else
4218         com_err(whoami, 0, "Unable to delete container %s from AD : %s",
4219                 av[CONTAINER_NAME], ldap_err2string(rc));
4220     }
4221   return(rc);
4222 }
4223
4224 int container_create(LDAP *ldap_handle, char *dn_path, int count, char **av)
4225 {
4226   char      *attr_array[3];
4227   LK_ENTRY  *group_base;
4228   int       group_count;
4229   LDAPMod   *mods[20];
4230   char      *objectClass_v[] = {"top", 
4231                            "organizationalUnit", 
4232                            NULL};
4233
4234   char *ou_v[] = {NULL, NULL};
4235   char *name_v[] = {NULL, NULL};
4236   char *moiraId_v[] = {NULL, NULL};
4237   char *desc_v[] = {NULL, NULL};
4238   char *managedBy_v[] = {NULL, NULL};
4239   char dName[256];
4240   char cName[256];
4241   char managedByDN[256];
4242   char filter[256];
4243   char temp[256];
4244   int  n;
4245   int  i;
4246   int  rc;
4247
4248   memset(filter, '\0', sizeof(filter));
4249   memset(dName, '\0', sizeof(dName));
4250   memset(cName, '\0', sizeof(cName));
4251   memset(managedByDN, '\0', sizeof(managedByDN));
4252   container_get_dn(av[CONTAINER_NAME], dName);
4253   container_get_name(av[CONTAINER_NAME], cName);
4254
4255   if ((strlen(cName) == 0) || (strlen(dName) == 0))
4256     {
4257       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", cName);
4258       return(AD_INVALID_NAME);
4259     }
4260
4261   if (!check_container_name(cName))
4262     {
4263       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", cName);
4264       return(AD_INVALID_NAME);
4265     }
4266
4267   n = 0;
4268   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
4269   name_v[0] = cName;
4270   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
4271   ou_v[0] = cName;
4272   ADD_ATTR("ou", ou_v, LDAP_MOD_ADD);
4273   if (strlen(av[CONTAINER_ROWID]) != 0)
4274     {
4275       moiraId_v[0] = av[CONTAINER_ROWID];
4276       ADD_ATTR("mitMoiraId", moiraId_v, LDAP_MOD_ADD);
4277     }
4278   if (strlen(av[CONTAINER_DESC]) != 0)
4279     {
4280       desc_v[0] = av[CONTAINER_DESC];
4281       ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
4282     }
4283   if ((strlen(av[CONTAINER_TYPE]) != 0) && (strlen(av[CONTAINER_ID]) != 0))
4284     {
4285           if (!strcasecmp(av[CONTAINER_TYPE], "KERBEROS"))
4286           {
4287                   if (!contact_create(ldap_handle, dn_path, av[CONTAINER_ID], kerberos_ou))
4288                   {
4289                         sprintf(managedByDN, "CN=%s,%s,%s", av[CONTAINER_ID], kerberos_ou,dn_path);
4290                         managedBy_v[0] = managedByDN;
4291                         ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_ADD);
4292                   }
4293           }
4294           else
4295           {
4296                 if (!strcasecmp(av[CONTAINER_TYPE], "USER"))
4297         {
4298           sprintf(filter, "(&(cn=%s)(&(objectCategory=person)(objectClass=user)))", av[CONTAINER_ID]);
4299         }
4300                 if (!strcasecmp(av[CONTAINER_TYPE], "LIST"))
4301         {
4302           sprintf(filter, "(&(objectClass=group)(cn=%s))", av[CONTAINER_ID]);
4303         }
4304                 if (strlen(filter) != 0)
4305         {
4306           attr_array[0] = "distinguishedName";
4307           attr_array[1] = NULL;
4308           group_count = 0;
4309           group_base = NULL;
4310           if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4311                                    &group_base, &group_count, LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
4312             {
4313               if (group_count == 1)
4314                 {
4315                   strcpy(managedByDN, group_base->value);
4316                   managedBy_v[0] = managedByDN;
4317                   ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_ADD);
4318                 }
4319               linklist_free(group_base);
4320               group_base = NULL;
4321               group_count = 0;
4322             }
4323         }
4324     }
4325   }
4326   mods[n] = NULL;
4327
4328   sprintf(temp, "%s,%s", dName, dn_path);
4329   rc = ldap_add_ext_s(ldap_handle, temp, mods, NULL, NULL);
4330   for (i = 0; i < n; i++)
4331     free(mods[i]);
4332   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
4333     {
4334       com_err(whoami, 0, "Unable to create container %s : %s",
4335               cName, ldap_err2string(rc));
4336       return(rc);
4337     }
4338   if (rc == LDAP_ALREADY_EXISTS)
4339     {
4340       if (strlen(av[CONTAINER_ROWID]) != 0)
4341         rc = container_adupdate(ldap_handle, dn_path, dName, "", count, av);
4342     }
4343   return(rc);
4344 }
4345
4346 int container_update(LDAP *ldap_handle, char *dn_path, int beforec, char **before, 
4347                      int afterc, char **after)
4348 {
4349   char distinguishedName[256];
4350   int  rc;
4351
4352   memset(distinguishedName, '\0', sizeof(distinguishedName));
4353   if (rc = container_get_distinguishedName(ldap_handle, dn_path, distinguishedName, afterc, after))
4354     return(rc);
4355   if (strlen(distinguishedName) == 0)
4356     {
4357       rc = container_create(ldap_handle, dn_path, afterc, after);
4358       return(rc);
4359     }
4360
4361   container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
4362   rc = container_adupdate(ldap_handle, dn_path, "", distinguishedName, afterc, after);
4363
4364   return(rc);
4365 }
4366
4367 int container_get_distinguishedName(LDAP *ldap_handle, char *dn_path, char *distinguishedName, int count, char **av)
4368 {
4369   char      *attr_array[3];
4370   LK_ENTRY  *group_base;
4371   int       group_count;
4372   char      dName[256];
4373   char      cName[256];
4374   char      filter[512];
4375   int       rc;
4376
4377   memset(filter, '\0', sizeof(filter));
4378   memset(dName, '\0', sizeof(dName));
4379   memset(cName, '\0', sizeof(cName));
4380   container_get_dn(av[CONTAINER_NAME], dName);
4381   container_get_name(av[CONTAINER_NAME], cName);
4382
4383   if (strlen(dName) == 0)
4384     {
4385       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", av[CONTAINER_NAME]);
4386       return(AD_INVALID_NAME);
4387     }
4388
4389   if (!check_container_name(cName))
4390     {
4391       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", cName);
4392       return(AD_INVALID_NAME);
4393     }
4394
4395   sprintf(filter, "(&(objectClass=organizationalUnit)(mitMoiraId=%s))", av[CONTAINER_ROWID]);
4396   attr_array[0] = "distinguishedName";
4397   attr_array[1] = NULL;
4398   group_count = 0;
4399   group_base = NULL;
4400   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4401                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
4402     {
4403       if (group_count == 1)
4404         {
4405           strcpy(distinguishedName, group_base->value);
4406         }
4407       linklist_free(group_base);
4408       group_base = NULL;
4409       group_count = 0;
4410     }
4411   if (strlen(distinguishedName) == 0)
4412     {
4413       sprintf(filter, "(&(objectClass=organizationalUnit)(distinguishedName=%s,%s))", dName, dn_path);
4414       attr_array[0] = "distinguishedName";
4415       attr_array[1] = NULL;
4416       group_count = 0;
4417       group_base = NULL;
4418       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4419                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
4420         {
4421           if (group_count == 1)
4422             {
4423               strcpy(distinguishedName, group_base->value);
4424             }
4425           linklist_free(group_base);
4426           group_base = NULL;
4427           group_count = 0;
4428         }
4429     }
4430   return(0);
4431 }
4432
4433 int container_adupdate(LDAP *ldap_handle, char *dn_path, char *dName, 
4434                        char *distinguishedName, int count, char **av)
4435 {
4436   char      *attr_array[5];
4437   LK_ENTRY  *group_base;
4438   LK_ENTRY  *pPtr;
4439   LDAPMod   *mods[20];
4440   int       group_count;
4441   char      filter[512];
4442   char      *moiraId_v[] = {NULL, NULL};
4443   char      *desc_v[] = {NULL, NULL};
4444   char      *managedBy_v[] = {NULL, NULL};
4445   char      managedByDN[256];
4446   char      moiraId[64];
4447   char      desc[256];
4448   char      ad_path[512];
4449   int       rc;
4450   int       i;
4451   int       n;
4452
4453
4454   strcpy(ad_path, distinguishedName);
4455   if (strlen(dName) != 0)
4456     sprintf(ad_path, "%s,%s", dName, dn_path);
4457
4458   sprintf(filter, "(&(objectClass=organizationalUnit)(distinguishedName=%s))", ad_path);
4459   if (strlen(av[CONTAINER_ID]) != 0)
4460     sprintf(filter, "(&(objectClass=organizationalUnit)(mitMoiraId=%s))", av[CONTAINER_ROWID]);
4461   attr_array[0] = "mitMoiraId";
4462   attr_array[1] = "description";
4463   attr_array[2] = "managedBy";
4464   attr_array[3] = NULL;
4465   group_count = 0;
4466   group_base = NULL;
4467   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4468                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != LDAP_SUCCESS)
4469     {
4470       com_err(whoami, 0, "Unable to retreive container info for %s : %s",
4471               av[CONTAINER_NAME], ldap_err2string(rc));
4472       return(rc);
4473     }
4474   memset(managedByDN, '\0', sizeof(managedByDN));
4475   memset(moiraId, '\0', sizeof(moiraId));
4476   memset(desc, '\0', sizeof(desc));
4477   pPtr = group_base;
4478   while (pPtr)
4479     {
4480       if (!strcasecmp(pPtr->attribute, "description"))
4481         strcpy(desc, pPtr->value);
4482       else if (!strcasecmp(pPtr->attribute, "managedBy"))
4483         strcpy(managedByDN, pPtr->value);
4484       else if (!strcasecmp(pPtr->attribute, "mitMoiraId"))
4485         strcpy(moiraId, pPtr->value);
4486       pPtr = pPtr->next;
4487     }
4488   linklist_free(group_base);
4489   group_base = NULL;
4490   group_count = 0;
4491
4492   n = 0;
4493   if (strlen(av[CONTAINER_ROWID]) != 0)
4494     {
4495       moiraId_v[0] = av[CONTAINER_ROWID];
4496       ADD_ATTR("mitMoiraId", moiraId_v, LDAP_MOD_REPLACE);
4497     }
4498   if (strlen(av[CONTAINER_DESC]) != 0)
4499     {
4500       attribute_update(ldap_handle, ad_path, av[CONTAINER_DESC], "description", dName);
4501     }
4502   else
4503     {
4504       if (strlen(desc) != 0)
4505         {
4506           attribute_update(ldap_handle, ad_path, "", "description", dName);
4507         }
4508     }
4509   if ((strlen(av[CONTAINER_TYPE]) != 0) && (strlen(av[CONTAINER_ID]) != 0))
4510     {
4511           if (!strcasecmp(av[CONTAINER_TYPE], "KERBEROS"))
4512           {
4513                   if (!contact_create(ldap_handle, dn_path, av[CONTAINER_ID], kerberos_ou))
4514                   {
4515                         sprintf(managedByDN, "CN=%s,%s,%s", av[CONTAINER_ID], kerberos_ou, dn_path);
4516                         managedBy_v[0] = managedByDN;
4517             ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_REPLACE);
4518                   }
4519                   else
4520                   {
4521                         if (strlen(managedByDN) != 0)
4522                         {
4523                 attribute_update(ldap_handle, ad_path, "", "managedBy", dName);
4524                         }
4525                   }
4526           }
4527           else
4528           {
4529                 memset(filter, '\0', sizeof(filter));
4530                 if (!strcasecmp(av[CONTAINER_TYPE], "USER"))
4531         {
4532           sprintf(filter, "(&(cn=%s)(&(objectCategory=person)(objectClass=user)))", av[CONTAINER_ID]);
4533         }
4534                 if (!strcasecmp(av[CONTAINER_TYPE], "LIST"))
4535         {
4536           sprintf(filter, "(&(objectClass=group)(cn=%s))", av[CONTAINER_ID]);
4537         }
4538                 if (strlen(filter) != 0)
4539         {
4540           attr_array[0] = "distinguishedName";
4541           attr_array[1] = NULL;
4542           group_count = 0;
4543           group_base = NULL;
4544           if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4545                                    &group_base, &group_count, LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
4546             {
4547               if (group_count == 1)
4548                 {
4549                   strcpy(managedByDN, group_base->value);
4550                   managedBy_v[0] = managedByDN;
4551                   ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_REPLACE);
4552                 }
4553               else
4554                 {
4555                   if (strlen(managedByDN) != 0)
4556                     {
4557                         attribute_update(ldap_handle, ad_path, "", "managedBy", dName);
4558                     }
4559                 }
4560               linklist_free(group_base);
4561               group_base = NULL;
4562               group_count = 0;
4563             }
4564         }
4565                 else
4566         {
4567           if (strlen(managedByDN) != 0)
4568             {
4569                 attribute_update(ldap_handle, ad_path, "", "managedBy", dName);
4570             }
4571         }
4572           }
4573     }
4574   mods[n] = NULL;
4575   if (n == 0)
4576     return(LDAP_SUCCESS);
4577
4578   rc = ldap_modify_s(ldap_handle, ad_path, mods);
4579   for (i = 0; i < n; i++)
4580     free(mods[i]);
4581   if (rc != LDAP_SUCCESS)
4582     {
4583         com_err(whoami, 0, "Unable to modify container info for %s : %s",
4584                 av[CONTAINER_NAME], ldap_err2string(rc));
4585         return(rc);
4586     }
4587   return(rc);
4588 }
4589
4590 int container_move_objects(LDAP *ldap_handle, char *dn_path, char *dName)
4591 {
4592   char      *attr_array[3];
4593   LK_ENTRY  *group_base;
4594   LK_ENTRY  *pPtr;
4595   int       group_count;
4596   char      filter[512];
4597   char      new_cn[128];
4598   char      temp[256];
4599   int       rc;
4600   int       NumberOfEntries = 10;
4601   int       i;
4602   int       count;
4603
4604   rc = ldap_set_option(ldap_handle, LDAP_OPT_SIZELIMIT, &NumberOfEntries);
4605
4606   for (i = 0; i < 3; i++)
4607     {
4608       memset(filter, '\0', sizeof(filter));
4609       if (i == 0)
4610         {
4611           strcpy(filter, "(!(|(objectClass=computer)(objectClass=organizationalUnit)))");
4612           attr_array[0] = "cn";
4613           attr_array[1] = NULL;
4614         }
4615       else if (i == 1)
4616         {
4617           strcpy(filter, "(objectClass=computer)");
4618           attr_array[0] = "cn";
4619           attr_array[1] = NULL;
4620         }
4621       else
4622         {
4623           strcpy(filter, "(objectClass=organizationalUnit)");
4624           attr_array[0] = "ou";
4625           attr_array[1] = NULL;
4626         }
4627
4628       while (1)
4629         {
4630           if ((rc = linklist_build(ldap_handle, dName, filter, attr_array, 
4631                                    &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != LDAP_SUCCESS)
4632             {
4633               break;
4634             }
4635           if (group_count == 0)
4636             break;
4637           pPtr = group_base;
4638           while(pPtr)
4639             {
4640               if (!strcasecmp(pPtr->attribute, "cn"))
4641                 {
4642                   sprintf(new_cn, "cn=%s", pPtr->value);
4643                   if (i == 0)
4644                     sprintf(temp, "%s,%s", orphans_other_ou, dn_path);
4645                   if (i == 1)
4646                     sprintf(temp, "%s,%s", orphans_machines_ou, dn_path);
4647                   count = 1;
4648                   while (1)
4649                     {
4650                       rc = ldap_rename_s(ldap_handle, pPtr->dn, new_cn, temp,
4651                                          TRUE, NULL, NULL);
4652                       if (rc == LDAP_ALREADY_EXISTS)
4653                         {
4654                           sprintf(new_cn, "cn=%s_%d", pPtr->value, count);
4655                           ++count;
4656                         }
4657                       else
4658                         break;
4659                     }
4660                 }
4661               else if (!strcasecmp(pPtr->attribute, "ou"))
4662                 {
4663                   rc = ldap_delete_s(ldap_handle, pPtr->dn);
4664                 }
4665               pPtr = pPtr->next;
4666             }
4667           linklist_free(group_base);
4668           group_base = NULL;
4669           group_count = 0;
4670         }
4671     }
4672   return(0);
4673 }
4674
4675 int get_machine_ou(LDAP *ldap_handle, char *dn_path, char *member, char *machine_ou, char *NewMachineName)
4676 {
4677   LK_ENTRY  *group_base;
4678   int  group_count;
4679   int  i;
4680   char filter[128];
4681   char *attr_array[3];
4682   char cn[256];
4683   char dn[256];
4684   char temp[256];
4685   char *pPtr;
4686   int   rc;
4687
4688   strcpy(NewMachineName, member);
4689   rc = moira_connect();
4690   rc = GetMachineName(NewMachineName);
4691   moira_disconnect();
4692   if (strlen(NewMachineName) == 0)
4693     {
4694       com_err(whoami, 0, "Unable to find alais for machine %s in Moira", member);
4695       return(1);
4696     }
4697
4698   pPtr = NULL;
4699   pPtr = strchr(NewMachineName, '.');
4700   if (pPtr != NULL)
4701     (*pPtr) = '\0';
4702
4703   group_base = NULL;
4704   group_count = 0;
4705   sprintf(filter, "(sAMAccountName=%s$)", NewMachineName);
4706   attr_array[0] = "cn";
4707   attr_array[1] = NULL;
4708   sprintf(temp, "%s", dn_path);
4709   if ((rc = linklist_build(ldap_handle, temp, filter, attr_array, 
4710                         &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
4711     {
4712       com_err(whoami, 0, "Unable to process machine %s : %s",
4713               member, ldap_err2string(rc));
4714       return(1);
4715     }
4716   if (group_count != 1)
4717     {
4718       com_err(whoami, 0, "Unable to process machine %s : machine not found in AD",
4719               NewMachineName);
4720       return(1);
4721     }
4722   strcpy(dn, group_base->dn);
4723   strcpy(cn, group_base->value);
4724   for (i = 0; i < (int)strlen(dn); i++)
4725     dn[i] = tolower(dn[i]);
4726   for (i = 0; i < (int)strlen(cn); i++)
4727     cn[i] = tolower(cn[i]);
4728   linklist_free(group_base);
4729   pPtr = NULL;
4730   pPtr = strstr(dn, cn);
4731   if (pPtr == NULL)
4732     {
4733       com_err(whoami, 0, "Unable to process machine %s",
4734               member);
4735       return(1);
4736     }
4737   pPtr += strlen(cn) + 1;
4738   strcpy(machine_ou, pPtr);
4739   pPtr = NULL;
4740   pPtr = strstr(machine_ou, "dc=");
4741   if (pPtr == NULL)
4742     {
4743       com_err(whoami, 0, "Unable to process machine %s",
4744               member);
4745       return(1);
4746     }
4747   --pPtr;
4748   (*pPtr) = '\0';
4749   return(0);
4750 }
4751
4752 int machine_move_to_ou(LDAP *ldap_handle, char * dn_path, char *MoiraMachineName, char *DestinationOu)
4753 {
4754
4755     char        NewCn[128];
4756     char        OldDn[512];
4757     char        MachineName[128];
4758     char        filter[128];
4759     char        *attr_array[3];
4760     char        NewOu[256];
4761     char        *cPtr = NULL;
4762     int         group_count;
4763     long        rc;
4764     LK_ENTRY    *group_base;
4765
4766     group_count = 0;
4767     group_base = NULL;
4768
4769     strcpy(MachineName, MoiraMachineName);
4770     rc = GetMachineName(MachineName);
4771     if (strlen(MachineName) == 0)
4772     {
4773         com_err(whoami, 0, "Unable to find alais for machine %s in Moira", MoiraMachineName);
4774         return(1);
4775     }
4776
4777     cPtr = strchr(MachineName, '.');
4778     if (cPtr != NULL)
4779         (*cPtr) = '\0';
4780     sprintf(filter, "(sAMAccountName=%s$)", MachineName);
4781     attr_array[0] = "sAMAccountName";
4782     attr_array[1] = NULL;
4783     if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, &group_base, 
4784                              &group_count, LDAP_SCOPE_SUBTREE)) != 0)
4785     {
4786         com_err(whoami, 0, "Unable to process machine %s : %s",
4787                 MoiraMachineName, ldap_err2string(rc));
4788         return(1);
4789     }
4790
4791     if (group_count == 1)
4792         strcpy(OldDn, group_base->dn);
4793     linklist_free(group_base);
4794     group_base = NULL;
4795     if (group_count != 1)
4796     {
4797         com_err(whoami, 0, "Unable to find machine %s in AD: %s", MoiraMachineName);
4798         return(1);
4799     }
4800     sprintf(NewOu, "%s,%s", DestinationOu, dn_path);
4801     cPtr = strchr(OldDn, ',');
4802     if (cPtr != NULL)
4803     {
4804         ++cPtr;
4805         if (!strcasecmp(cPtr, NewOu))
4806             return(0);
4807     }
4808     sprintf(NewCn, "CN=%s", MachineName);
4809     rc = ldap_rename_s(ldap_handle, OldDn, NewCn, NewOu, TRUE, NULL, NULL);
4810     return(rc);
4811 }
4812
4813 int machine_check(LDAP *ldap_handle, char *dn_path, char *machine_name)
4814 {
4815     char    Name[128];
4816     char    *pPtr;
4817     int     rc;
4818
4819     memset(Name, '\0', sizeof(Name));
4820     strcpy(Name, machine_name);
4821     pPtr = NULL;
4822     pPtr = strchr(Name, '.');
4823     if (pPtr != NULL)
4824         (*pPtr) = '\0';
4825     strcat(Name, "$");
4826     return(!(rc = checkADname(ldap_handle, dn_path, Name)));
4827 }
4828
4829 int machine_get_moira_container(LDAP *ldap_handle, char *dn_path, char *machine_name, char *container_name)
4830 {
4831     int     rc;
4832     char    *av[2];
4833     char    *call_args[2];
4834
4835     av[0] = machine_name;
4836     call_args[0] = (char *)container_name;
4837     rc = mr_query("get_machine_to_container_map", 1, av, machine_GetMoiraContainer,
4838                    call_args);
4839     return(rc);
4840 }
4841
4842 int machine_GetMoiraContainer(int ac, char **av, void *ptr)
4843 {
4844     char **call_args;
4845     
4846     call_args = ptr;
4847     strcpy(call_args[0], av[1]);
4848     return(0);
4849 }
4850
4851 int Moira_container_group_create(char **after)
4852 {
4853   long rc;
4854   char GroupName[64];
4855   char *argv[20];
4856   
4857   memset(GroupName, '\0', sizeof(GroupName));
4858   rc = Moira_groupname_create(GroupName, after[CONTAINER_NAME], 
4859                               after[CONTAINER_ROWID]);
4860   if (rc)
4861     return rc;
4862   
4863   argv[L_NAME] = GroupName;
4864   argv[L_ACTIVE] = "1";
4865   argv[L_PUBLIC] = "0";
4866   argv[L_HIDDEN] = "0";
4867   argv[L_MAILLIST] = "0";
4868   argv[L_GROUP] = "1";
4869   argv[L_GID] = UNIQUE_GID;
4870   argv[L_NFSGROUP] = "0";
4871   argv[L_MAILMAN] = "0";
4872   argv[L_MAILMAN_SERVER] = "[NONE]";
4873   argv[L_DESC] = "auto created container group";
4874   argv[L_ACE_TYPE] = "USER";
4875   argv[L_MEMACE_TYPE] = "USER";
4876   argv[L_ACE_NAME] = "sms";
4877   argv[L_MEMACE_NAME] = "sms";
4878
4879   if (rc = mr_query("add_list", 15, argv, NULL, NULL))
4880     {
4881       com_err(whoami, 0, "Unable to create container group %s for container %s: %s",
4882               GroupName, after[CONTAINER_NAME], error_message(rc));
4883     }
4884
4885   Moira_setContainerGroup(after[CONTAINER_NAME], GroupName);
4886   Moira_addGroupToParent(after[CONTAINER_NAME], GroupName);
4887   
4888   return(rc);
4889 }
4890
4891 int Moira_container_group_update(char **before, char **after)
4892 {
4893   long rc;
4894   char BeforeGroupName[64];
4895   char AfterGroupName[64];
4896   char *argv[20];
4897   
4898   if (!strcasecmp(after[CONTAINER_NAME], before[CONTAINER_NAME]))
4899     return(0);
4900
4901   memset(BeforeGroupName, '\0', sizeof(BeforeGroupName));
4902   Moira_getGroupName(after[CONTAINER_NAME], BeforeGroupName, 0);
4903   if (strlen(BeforeGroupName) == 0)
4904     return(0);
4905
4906   memset(AfterGroupName, '\0', sizeof(AfterGroupName));
4907   rc = Moira_groupname_create(AfterGroupName, after[CONTAINER_NAME], 
4908                               after[CONTAINER_ROWID]);
4909   if (rc)
4910     return rc;
4911
4912   if (strcasecmp(BeforeGroupName, AfterGroupName))
4913     {
4914       argv[L_NAME] = BeforeGroupName;
4915       argv[L_NAME + 1] = AfterGroupName;
4916       argv[L_ACTIVE + 1] = "1";
4917       argv[L_PUBLIC + 1] = "0";
4918       argv[L_HIDDEN + 1] = "0";
4919       argv[L_MAILLIST + 1] = "0";
4920       argv[L_GROUP + 1] = "1";
4921       argv[L_GID + 1] = UNIQUE_GID;
4922       argv[L_NFSGROUP + 1] = "0";
4923       argv[L_MAILMAN + 1] = "0";
4924       argv[L_MAILMAN_SERVER + 1] = "[NONE]";
4925       argv[L_DESC + 1] = "auto created container group";
4926       argv[L_ACE_TYPE + 1] = "USER";
4927       argv[L_MEMACE_TYPE + 1] = "USER";
4928       argv[L_ACE_NAME + 1] = "sms";
4929       argv[L_MEMACE_NAME + 1] = "sms";
4930       
4931       if (rc = mr_query("update_list", 16, argv, NULL, NULL))
4932         {
4933           com_err(whoami, 0, "Unable to rename container group from %s to %s: %s",
4934                   BeforeGroupName, AfterGroupName, error_message(rc));
4935         }
4936     }
4937   
4938   return(rc);
4939 }
4940
4941 int Moira_container_group_delete(char **before)
4942 {
4943   long rc = 0;
4944   char *argv[13];
4945   char GroupName[64];
4946   char ParentGroupName[64];
4947   
4948   memset(ParentGroupName, '\0', sizeof(ParentGroupName));
4949   Moira_getGroupName(before[CONTAINER_NAME], ParentGroupName, 1);
4950
4951   memset(GroupName, '\0', sizeof(GroupName));
4952   if (strcmp(before[CONTAINER_GROUP_NAME], "[none]"))
4953     strcpy(GroupName, before[CONTAINER_GROUP_NAME]);
4954   
4955   if ((strlen(ParentGroupName) != 0) && (strlen(GroupName) != 0))
4956     {
4957       argv[0] = ParentGroupName;
4958       argv[1] = "LIST";
4959       argv[2] = GroupName;
4960       if (rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL))
4961         {
4962           com_err(whoami, 0, "Unable to delete container group %s from list: %s",
4963                   GroupName, ParentGroupName, error_message(rc));
4964         }
4965     }
4966   
4967   if (strlen(GroupName) != 0)
4968     {
4969       argv[0] = GroupName;
4970       if (rc = mr_query("delete_list", 1, argv, NULL, NULL))
4971         {
4972           com_err(whoami, 0, "Unable to delete container group %s : %s",
4973                   GroupName, error_message(rc));
4974         }
4975      }
4976   
4977   return(rc);
4978 }
4979
4980 int Moira_groupname_create(char *GroupName, char *ContainerName,
4981                            char *ContainerRowID)
4982 {
4983   char *ptr;
4984   char *ptr1;
4985   char temp[64];
4986   char newGroupName[64];
4987   char tempGroupName[64];
4988   char tempgname[64];
4989   char *argv[1];
4990   int  i;
4991   long rc;
4992
4993   strcpy(temp, ContainerName);
4994   
4995   ptr1 = strrchr(temp, '/');
4996   if (ptr1 != NULL)
4997   {
4998     *ptr1 = '\0';
4999     ptr = ++ptr1;
5000     ptr1 = strrchr(temp, '/');
5001     if (ptr1 != NULL)
5002     {
5003         sprintf(tempgname, "%s-%s", ++ptr1, ptr);
5004     }
5005     else
5006         strcpy(tempgname, ptr);
5007   }
5008   else
5009     strcpy(tempgname, temp);
5010
5011   if (strlen(tempgname) > 25)
5012     tempgname[25] ='\0';
5013
5014   sprintf(newGroupName, "cnt-%s", tempgname);
5015
5016   /* change everything to lower case */
5017   ptr = newGroupName;
5018   while (*ptr)
5019     {
5020       if (isupper(*ptr))
5021         *ptr = tolower(*ptr);
5022       if (*ptr == ' ')
5023         *ptr = '-';
5024       ptr++;
5025     }
5026
5027   strcpy(tempGroupName, newGroupName);
5028   i = (int)'0';
5029   /* append 0-9 then a-z if a duplicate is found */
5030   while(1)
5031     {
5032       argv[0] = newGroupName;
5033       if (rc = mr_query("get_list_info", 1, argv, NULL, NULL))
5034         {
5035           if (rc == MR_NO_MATCH)
5036             break;
5037           com_err(whoami, 0, "Moira error while creating group name for container %s : %s",
5038                   ContainerName, error_message(rc));
5039           return rc;
5040         }
5041       sprintf(newGroupName, "%s-%c", tempGroupName, i);
5042       if (i == (int)'z')
5043         {
5044           com_err(whoami, 0, "Unable to find a unique group name for container %s: too many duplicate container names",
5045                   ContainerName);
5046           return 1;
5047         }
5048       if (i == '9')
5049         i = 'a';
5050       else
5051         i++;
5052     }
5053
5054   strcpy(GroupName, newGroupName);
5055   return(0);
5056 }
5057
5058 int Moira_setContainerGroup(char *origContainerName, char *GroupName)
5059 {
5060   long rc;
5061   char *argv[3];
5062   
5063   argv[0] = origContainerName;
5064   argv[1] = GroupName;
5065
5066   if ((rc = mr_query("set_container_list", 2, argv, NULL, NULL)))
5067     {
5068          com_err(whoami, 0, "Unable to set container group %s in container %s: %s",
5069                  GroupName, origContainerName, error_message(rc));
5070     }
5071
5072   return(0);
5073 }
5074
5075  int Moira_addGroupToParent(char *origContainerName, char *GroupName)
5076  {
5077    char ContainerName[64];
5078    char ParentGroupName[64];
5079    char *argv[3];
5080    long rc;
5081
5082    strcpy(ContainerName, origContainerName);
5083
5084    Moira_getGroupName(ContainerName, ParentGroupName, 1);
5085    /* top-level container */
5086    if (strlen(ParentGroupName) == 0)
5087      return(0);
5088    
5089    argv[0] = ParentGroupName;
5090    argv[1] = "LIST";
5091    argv[2] = GroupName;
5092    if ((rc = mr_query("add_member_to_list", 3, argv, NULL, NULL)))
5093      {
5094        com_err(whoami, 0, "Unable to add container group %s to parent group %s: %s",
5095                GroupName, ParentGroupName, error_message(rc));
5096      }
5097    return(0);
5098  }
5099
5100 int Moira_getContainerGroup(int ac, char **av, void *ptr)
5101 {
5102   char **call_args;
5103   
5104   call_args = ptr;
5105   strcpy(call_args[0], av[1]);
5106   return(0);
5107 }
5108
5109 int Moira_getGroupName(char *origContainerName, char *GroupName,
5110                        int ParentFlag)
5111 {
5112   char ContainerName[64];
5113   char *argv[3];
5114   char *call_args[3];
5115   char *ptr;
5116   long rc;
5117
5118   strcpy(ContainerName, origContainerName);
5119
5120   if (ParentFlag)
5121     {
5122       ptr = strrchr(ContainerName, '/');
5123       if (ptr != NULL)
5124         (*ptr) = '\0';
5125       else
5126         return(0);
5127     }
5128
5129   argv[0] = ContainerName;
5130   argv[1] = NULL;
5131   call_args[0] = GroupName;
5132   call_args[1] = NULL;
5133
5134   if (!(rc = mr_query("get_container_list", 1, argv, Moira_getContainerGroup,
5135                       call_args)))
5136     {
5137       if (strlen(GroupName) != 0)
5138         return(0);
5139     }
5140
5141   if (rc)
5142     com_err(whoami, 0, "Unable to get container group from container %s: %s",
5143             ContainerName, error_message(rc));
5144   else
5145     com_err(whoami, 0, "Unable to get container group from container %s",
5146             ContainerName);
5147      return(0);
5148 }
5149
5150 int Moira_process_machine_container_group(char *MachineName, char* GroupName, 
5151                                           int DeleteMachine)
5152 {
5153   char *argv[3];
5154   long rc;
5155
5156   if (strcmp(GroupName, "[none]") == 0)
5157     return 0;
5158
5159   argv[0] = GroupName;
5160   argv[1] = "MACHINE";
5161   argv[2] = MachineName;
5162   if (!DeleteMachine)
5163     rc = mr_query("add_member_to_list", 3, argv, NULL, NULL);
5164   else
5165     rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL);
5166   if (rc)
5167     {
5168       com_err(whoami, 0, "Unable to add machine %s to container group%s: %s",
5169               MachineName, GroupName, error_message(rc));
5170     }
5171   return(0);
5172 }
5173
5174 int GetMachineName(char *MachineName)
5175 {
5176         char    *args[2];
5177     char    NewMachineName[1024];
5178     char    *szDot;
5179     int     rc = 0;
5180     int     i;
5181     DWORD   dwLen = 0;
5182     char    *call_args[2];
5183
5184     // If the address happens to be in the top-level MIT domain, great!
5185     strcpy(NewMachineName, MachineName);
5186     for (i = 0; i < (int)strlen(NewMachineName); i++)
5187         NewMachineName[i] = toupper(NewMachineName[i]);
5188     szDot = strchr(NewMachineName,'.');
5189     if ((szDot) && (!strcasecmp(szDot+1, DOMAIN_SUFFIX)))
5190     {
5191         return(0);
5192     }
5193         
5194     // If not, see if it has a Moira alias in the top-level MIT domain.
5195     memset(NewMachineName, '\0', sizeof(NewMachineName));
5196         args[0] = "*";
5197     args[1] = MachineName;
5198     call_args[0] = NewMachineName;
5199     call_args[1] = NULL;
5200     if (rc = mr_query("get_hostalias", 2, args, ProcessMachineName, call_args))
5201     {
5202         com_err(whoami, 0, "Unable to resolve machine name %s : %s",
5203                 MachineName, error_message(rc));
5204         strcpy(MachineName, "");
5205         return(0);
5206     }
5207
5208     if (strlen(NewMachineName) != 0)
5209         strcpy(MachineName, NewMachineName);
5210     else
5211         strcpy(MachineName, "");
5212     return(0);
5213
5214 }
5215
5216 int ProcessMachineName(int ac, char **av, void *ptr)
5217 {
5218     char    **call_args;
5219     char    MachineName[1024];
5220     char    *szDot;
5221     int     i;
5222
5223     call_args = ptr;
5224     if (strlen(call_args[0]) == 0)
5225     {
5226         strcpy(MachineName, av[0]);
5227         for (i = 0; i < (int)strlen(MachineName); i++)
5228             MachineName[i] = toupper(MachineName[i]);
5229         szDot = strchr(MachineName,'.');
5230         if ((szDot) && (!strcasecmp(szDot+1,DOMAIN_SUFFIX)))
5231         {
5232             strcpy(call_args[0], MachineName);
5233         }
5234     }
5235     return(0);
5236 }
5237
5238 void SwitchSFU(LDAPMod **mods, int *UseSFU30, int n)
5239 {
5240     int i;
5241
5242     if (*UseSFU30)
5243     {
5244         for (i = 0; i < n; i++)
5245         {
5246             if (!strcmp(mods[i]->mod_type, "msSFU30UidNumber"))
5247                 mods[i]->mod_type = "uidNumber";
5248         }
5249         (*UseSFU30) = 0;
5250     }
5251     else
5252     {
5253         for (i = 0; i < n; i++)
5254         {
5255             if (!strcmp(mods[i]->mod_type, "uidNumber"))
5256                 mods[i]->mod_type = "msSFU30UidNumber";
5257         }
5258         (*UseSFU30) = 1;
5259     }
5260 }
5261
5262 int SetHomeDirectory(LDAP *ldap_handle, char *user_name, char *DistinguishedName,
5263                      char *WinHomeDir, char *WinProfileDir,
5264                      char **homedir_v, char **winProfile_v,
5265                      char **drives_v, LDAPMod **mods, 
5266                      int OpType, int n)
5267 {
5268     char **hp;
5269     char cWeight[3];
5270     char cPath[1024];
5271     char path[1024];
5272     char winPath[1024];
5273     char winProfile[1024];
5274     char homeDrive[8];
5275     int  last_weight;
5276     int  i;
5277     int  rc;
5278     LDAPMod *DelMods[20];
5279
5280     memset(homeDrive, '\0', sizeof(homeDrive));
5281     memset(path, '\0', sizeof(path));
5282     memset(winPath, '\0', sizeof(winPath));
5283     memset(winProfile, '\0', sizeof(winProfile));
5284     hp = NULL;
5285     if ((!strcasecmp(WinHomeDir, "[afs]")) || (!strcasecmp(WinProfileDir, "[afs]")))
5286     {
5287         if ((hp = hes_resolve(user_name, "filsys")) != NULL)
5288         {
5289             memset(cWeight, 0, sizeof(cWeight));
5290             memset(cPath, 0, sizeof(cPath));
5291             last_weight = 1000;
5292             i = 0;
5293             while (hp[i] != NULL)
5294             {
5295                 if (sscanf(hp[i], "%*s %s", cPath))
5296                 {
5297                     if (strnicmp(cPath, AFS, strlen(AFS)) == 0)
5298                     {
5299                         if (sscanf(hp[i], "%*s %*s %*s %*s %s", cWeight))
5300                         {
5301                             if (atoi(cWeight) < last_weight)
5302                             {
5303                                 strcpy(path, cPath);
5304                                 last_weight = (int)atoi(cWeight);
5305                             }
5306                         }
5307                         else 
5308                             strcpy(path, cPath);
5309                     }
5310                 }
5311               ++i;
5312             }
5313             if (strlen(path))
5314             {
5315                 if (!strnicmp(path, AFS, strlen(AFS)))
5316                 {
5317                     AfsToWinAfs(path, winPath);
5318                     strcpy(winProfile, winPath);
5319                     strcat(winProfile, "\\.winprofile");
5320                 }
5321             }
5322         }
5323         else
5324             return(n);
5325     }
5326
5327     if ((!strcasecmp(WinHomeDir, "[dfs]")) || (!strcasecmp(WinProfileDir, "[dfs]")))
5328     {
5329         sprintf(path, "\\\\%s\\dfs\\profiles\\%c\\%s", ldap_domain, user_name[0], user_name);
5330         if (!strcasecmp(WinProfileDir, "[dfs]"))
5331           {
5332             strcpy(winProfile, path);
5333             strcat(winProfile, "\\.winprofile");
5334           }
5335         if (!strcasecmp(WinHomeDir, "[dfs]"))
5336           strcpy(winPath, path);
5337     }
5338
5339     if (hp != NULL)
5340     {
5341         i = 0;
5342         while (hp[i])
5343         {
5344             free(hp[i]);
5345             i++;
5346         }
5347     }
5348
5349     if (!strcasecmp(WinHomeDir, "[local]"))
5350         memset(winPath, '\0', sizeof(winPath));
5351     else if (!strcasecmp(WinHomeDir, "[afs]") || !strcasecmp(WinHomeDir, "[dfs]"))
5352     {
5353         strcpy(homeDrive, "H:");
5354     }
5355     else
5356     {
5357         strcpy(winPath, WinHomeDir);
5358         if (!strncmp(WinHomeDir, "\\\\", 2))
5359         {
5360             strcpy(homeDrive, "H:");
5361         }        
5362     }
5363
5364     // nothing needs to be done if WinProfileDir is [afs].
5365     if (!strcasecmp(WinProfileDir, "[local]"))
5366         memset(winProfile, '\0', sizeof(winProfile));
5367     else if (strcasecmp(WinProfileDir, "[afs]") && strcasecmp(WinProfileDir, "[dfs]"))
5368     {
5369         strcpy(winProfile, WinProfileDir);
5370     }
5371
5372     if (strlen(winProfile) != 0)
5373     {
5374         if (winProfile[strlen(winProfile) - 1] == '\\')
5375             winProfile[strlen(winProfile) - 1] = '\0';
5376     }
5377     if (strlen(winPath) != 0)
5378     {
5379         if (winPath[strlen(winPath) - 1] == '\\')
5380             winPath[strlen(winPath) - 1] = '\0';
5381     }
5382
5383     if ((winProfile[1] == ':') && (strlen(winProfile) == 2))
5384         strcat(winProfile, "\\");
5385     if ((winPath[1] == ':') && (strlen(winPath) == 2))
5386         strcat(winPath, "\\");
5387
5388     if (strlen(winPath) == 0)
5389     {
5390         if (OpType == LDAP_MOD_REPLACE)
5391         {
5392             i = 0;
5393             DEL_ATTR("homeDirectory", LDAP_MOD_DELETE);
5394             DelMods[i] = NULL;
5395             //unset homeDirectory attribute for user.
5396             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
5397             free(DelMods[0]);
5398         }
5399     }
5400     else
5401     {
5402         homedir_v[0] = strdup(winPath);
5403         ADD_ATTR("homeDirectory", homedir_v, OpType);
5404     }
5405
5406     if (strlen(winProfile) == 0)
5407     {
5408         if (OpType == LDAP_MOD_REPLACE)
5409         {
5410             i = 0;
5411             DEL_ATTR("profilePath", LDAP_MOD_DELETE);
5412             DelMods[i] = NULL;
5413             //unset profilePate attribute for user.
5414             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
5415             free(DelMods[0]);
5416         }
5417     }
5418     else
5419     {
5420         winProfile_v[0] = strdup(winProfile);
5421         ADD_ATTR("profilePath", winProfile_v, OpType);
5422     }
5423
5424     if (strlen(homeDrive) == 0)
5425     {
5426         if (OpType == LDAP_MOD_REPLACE)
5427         {
5428             i = 0;
5429             DEL_ATTR("homeDrive", LDAP_MOD_DELETE);
5430             DelMods[i] = NULL;
5431             //unset homeDrive attribute for user
5432             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
5433             free(DelMods[0]);
5434         }
5435     }
5436     else
5437     {
5438         drives_v[0] = strdup(homeDrive);
5439         ADD_ATTR("homeDrive", drives_v, OpType);
5440     }
5441
5442     return(n);
5443 }
5444
5445 int GetServerList(char *ldap_domain, char **ServerList)
5446 {
5447   unsigned long   rc;
5448   int             group_count;
5449   int             UseSFU30;
5450   int             Count;
5451   int             i;
5452   int             k;
5453   int             ServerListFound;
5454   char            default_server[256];
5455   char            dn_path[256];
5456   char            *attr_array[3];
5457   char            *sPtr;
5458   char            base[128];
5459   char            filter[128];
5460   char            temp[128];
5461   LK_ENTRY        *group_base;
5462   LK_ENTRY        *gPtr;
5463   LDAP            *ldap_handle;
5464   FILE            *fptr;
5465
5466   memset(default_server, '\0', sizeof(default_server));
5467   memset(dn_path, '\0', sizeof(dn_path));
5468   for (i = 0; i < MAX_SERVER_NAMES; i++)
5469     {
5470       if (ServerList[i] != NULL)
5471         {
5472           free(ServerList[i]);
5473           ServerList[i] = NULL;
5474         }
5475     }
5476   if (rc = ad_connect(&ldap_handle, ldap_domain, dn_path, "", "", default_server, 0, 
5477                       ServerList))
5478       return(1);
5479
5480   for (i = 0; i < MAX_SERVER_NAMES; i++)
5481     {
5482       ServerList[i] = NULL;
5483     }
5484
5485   memset(ServerList, '\0', sizeof(ServerList[0]) * MAX_SERVER_NAMES);
5486   group_count = 0;
5487   group_base = NULL;
5488   Count = 0;
5489   ServerListFound = 0;
5490
5491   strcpy(filter, "(&(objectClass=rIDManager)(fSMORoleOwner=*))");
5492   attr_array[0] = "fSMORoleOwner";
5493   attr_array[1] = NULL;
5494   if (!(rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
5495                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
5496     {
5497       if (group_count != 0)
5498         {
5499           sPtr = strstr(group_base->value, ",CN=");
5500           if (sPtr != NULL)
5501             {
5502               sPtr += strlen(",CN=");
5503               if (ServerList[0] == NULL)
5504                   ServerList[0] = calloc(1, 256);
5505               strcpy(ServerList[0], sPtr);
5506               sPtr = strstr(ServerList[0], ",");
5507               if (sPtr != NULL)
5508                   (*sPtr) = '\0';
5509               ++Count;
5510               ServerListFound = 1;
5511             }
5512         }
5513     }
5514   linklist_free(group_base);
5515
5516   group_count = 0;
5517   group_base = NULL;
5518   attr_array[0] = "cn";
5519   attr_array[1] = NULL;
5520   strcpy(filter, "(cn=*)");
5521   sprintf(base, "cn=Servers,cn=Default-First-Site-Name,cn=Sites,cn=Configuration,%s", dn_path);
5522
5523   if (!(rc = linklist_build(ldap_handle, base, filter, attr_array, 
5524                            &group_base, &group_count, LDAP_SCOPE_ONELEVEL)) != 0)
5525     {
5526       if (group_count != 0)
5527         {
5528           gPtr = group_base;
5529           while (gPtr != NULL)
5530             {
5531               if (ServerListFound != 0)
5532                 {
5533                   if (!strcasecmp(ServerList[0], gPtr->value))
5534                     {
5535                       gPtr = gPtr->next;
5536                       continue;
5537                     }
5538                 }
5539               if (Count < MAX_SERVER_NAMES)
5540                 {
5541                   if (ServerList[Count] == NULL)
5542                       ServerList[Count] = calloc(1, 256);
5543                   strcpy(ServerList[Count], gPtr->value);
5544                   gPtr = gPtr->next;
5545                   ++Count;
5546                 }
5547             }
5548         }
5549     }
5550   linklist_free(group_base);
5551
5552   UseSFU30 = 0;
5553   group_count = 0;
5554   group_base = NULL;
5555
5556   strcpy(filter, "(cn=msSFU-30-Uid-Number)");
5557   sprintf(base, "cn=schema,cn=configuration,%s", dn_path);
5558
5559   if (!(rc = linklist_build(ldap_handle, base, filter, NULL, 
5560                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
5561     {
5562       if (group_count != 0)
5563         {
5564           UseSFU30 = 1;
5565         }
5566     }
5567   linklist_free(group_base);
5568   group_count = 0;
5569   group_base = NULL;
5570
5571   sprintf(temp, "%s%s.cfg", CFG_PATH, ldap_domain);
5572   if ((fptr = fopen(temp, "w+")) != NULL)
5573     {
5574       fprintf(fptr, "%s %s\n", DOMAIN, ldap_domain);
5575       if (strlen(PrincipalName) != 0)
5576           fprintf(fptr, "%s %s\n", PRINCIPALNAME, PrincipalName);
5577       if (UseSFU30)
5578           fprintf(fptr, "%s %s\n", MSSFU, SFUTYPE);
5579       for (i = 0; i < MAX_SERVER_NAMES; i++)
5580         {
5581           if (ServerList[i] != NULL)
5582             {
5583               fprintf(fptr, "%s %s\n", SERVER, ServerList[i]);
5584             }
5585         }
5586       fclose(fptr);
5587     }
5588   ldap_unbind_s(ldap_handle);
5589
5590   for (i = 0; i < MAX_SERVER_NAMES; i++)
5591     {
5592       if (ServerList[i] != NULL)
5593         {
5594           if (ServerList[i][strlen(ServerList[i]) - 1] == '\n')
5595               ServerList[i][strlen(ServerList[i]) - 1] = '\0';
5596           strcat(ServerList[i], ".");
5597           strcat(ServerList[i], ldap_domain);
5598           for (k = 0; k < (int)strlen(ServerList[i]); k++)
5599               ServerList[i][k] = toupper(ServerList[i][k]);
5600         }
5601     }
5602
5603   return(0);
5604 }
5605
5606 int attribute_update(LDAP *ldap_handle, char *distinguished_name, 
5607                       char *attribute_value, char *attribute, char *user_name)
5608 {
5609   char      *mod_v[] = {NULL, NULL};
5610   LDAPMod   *DelMods[20];
5611   LDAPMod   *mods[20];
5612   int       n;
5613   int       i;
5614   int       rc;
5615
5616   if (strlen(attribute_value) == 0)
5617     {
5618       i = 0;
5619       DEL_ATTR(attribute, LDAP_MOD_DELETE);
5620       DelMods[i] = NULL;
5621       rc = ldap_modify_s(ldap_handle, distinguished_name, DelMods);
5622       free(DelMods[0]);
5623     }
5624     else
5625     {
5626       n = 0;
5627       mod_v[0] = attribute_value;
5628       ADD_ATTR(attribute, mod_v, LDAP_MOD_REPLACE);
5629       mods[n] = NULL;
5630       if ((rc = ldap_modify_s(ldap_handle, distinguished_name, mods)) != LDAP_SUCCESS)
5631         {
5632           free(mods[0]);
5633           n = 0;
5634           mod_v[0] = attribute_value;
5635           ADD_ATTR(attribute, mod_v, LDAP_MOD_ADD);
5636           mods[n] = NULL;
5637           if ((rc = ldap_modify_s(ldap_handle, distinguished_name, mods)) != LDAP_SUCCESS)
5638             {
5639               com_err(whoami, 0, "Unable to change the %s attribute for %s in the AD : %s",
5640                       attribute, user_name, ldap_err2string(rc));
5641             }
5642         }
5643       free(mods[0]);
5644     }
5645   return(rc);
5646 }
5647
5648 int tickets_get_k5()
5649 {
5650     char temp[128];
5651     char KinitPath[128];
5652     int  retval;
5653     int  i;
5654     static char EnvVar[128];
5655     static char EnvVar1[128];
5656
5657     strcpy(EnvVar, KRB5CCNAME);
5658     retval = putenv(EnvVar);
5659     strcpy(EnvVar1, KRBTKFILE);
5660     retval = putenv(EnvVar1);
5661
5662     for (i = 0; i < (int)strlen(PrincipalName); i++)
5663         PrincipalName[i] = tolower(PrincipalName[i]);
5664     if (strlen(PrincipalName) == 0)
5665     {
5666         strcpy(PrincipalName, PRODUCTION_PRINCIPAL);
5667         if (strcasecmp(ldap_domain, PRIMARY_DOMAIN))
5668             strcpy(PrincipalName, TEST_PRINCIPAL);
5669     }
5670
5671     memset(KinitPath, '\0',sizeof(KinitPath));
5672 #ifndef _WIN32
5673     strcpy(KinitPath, "/usr/athena/bin/");
5674 #endif
5675     sprintf(temp, "%skinit -k -t %s %s", KinitPath, KEYTABFILE, PrincipalName);
5676     retval = system(temp);
5677     if (retval)
5678       {
5679         com_err(whoami, 0, "%s failed", temp);
5680         sprintf(temp, "%skinit -5 -k -t %s %s", KinitPath, KEYTABFILE, PrincipalName);
5681         retval = system(temp);
5682         if (retval)
5683           {
5684             com_err(whoami, 0, "%s failed", temp);
5685             return(-1);
5686           }
5687       }
5688     return(0);
5689 }
5690
5691 int get_tickets()
5692 {
5693
5694     if (tickets_get_k5())
5695     {
5696         sleep(1);
5697         if (tickets_get_k5())
5698           {
5699             com_err(whoami, 0, "%s", "Unable to get kerberos tickets");
5700             critical_alert("AD incremental", "%s",
5701                            "winad.incr incremental failed (unable to get kerberos tickets)");
5702             return(1);
5703           }
5704     }
5705     return(0);
5706 }
5707
5708 int destroy_cache(void)
5709 {
5710   krb5_context          context;
5711   krb5_ccache                   cache;
5712   krb5_error_code       rc;
5713
5714   context = NULL;
5715   cache = NULL;
5716   if (!krb5_init_context(&context))
5717     {
5718       if (!krb5_cc_default(context, &cache))
5719         rc = krb5_cc_destroy(context, cache);
5720     }
5721   if (context != NULL)
5722     krb5_free_context(context);
5723   dest_tkt();
5724
5725   return(rc);
5726 }
5727
5728
5729 void StringTrim(char *StringToTrim)
5730 {
5731     char    *cPtr;
5732     char    temp[256];
5733     int     i;
5734
5735     if (strlen(StringToTrim) == 0)
5736         return;
5737
5738     cPtr = StringToTrim;
5739     while (isspace(*cPtr))
5740     {
5741         ++cPtr;
5742     }
5743     strcpy(temp, cPtr);
5744     if (strlen(temp) == 0)
5745     {
5746         strcpy(StringToTrim, temp);
5747         return;
5748     }
5749     while (1)
5750     {
5751         i = strlen(temp);
5752         if (i == 0)
5753             break;
5754         if (!isspace(temp[i-1]))
5755             break;
5756         temp[i-1] = '\0';
5757     }
5758
5759     strcpy(StringToTrim, temp);
5760     return;
5761 }
5762
5763 int ReadConfigFile(char *DomainName)
5764 {
5765     int     Count;
5766     int     i;
5767     int     k;
5768     char    temp[256];
5769     char    temp1[256];
5770     FILE    *fptr;
5771
5772     Count = 0;
5773
5774     sprintf(temp, "%s%s.cfg", CFG_PATH, DomainName);
5775     if ((fptr = fopen(temp, "r")) != NULL)
5776     {
5777         while (fgets(temp, sizeof(temp), fptr) != 0)
5778         {
5779             for (i = 0; i < (int)strlen(temp); i++)
5780                 temp[i] = toupper(temp[i]);
5781             if (temp[strlen(temp) - 1] == '\n')
5782                 temp[strlen(temp) - 1] = '\0';
5783             StringTrim(temp);
5784             if (strlen(temp) == 0)
5785                 continue;
5786             if (!strncmp(temp, DOMAIN, strlen(DOMAIN)))
5787             {
5788                 if (strlen(temp) > (strlen(DOMAIN)))
5789                 {
5790                     strcpy(ldap_domain, &temp[strlen(DOMAIN)]);
5791                     StringTrim(ldap_domain);
5792                 }
5793             }
5794             else if (!strncmp(temp, PRINCIPALNAME, strlen(PRINCIPALNAME)))
5795             {
5796                 if (strlen(temp) > (strlen(PRINCIPALNAME)))
5797                 {
5798                     strcpy(PrincipalName, &temp[strlen(PRINCIPALNAME)]);
5799                     StringTrim(PrincipalName);
5800                 }
5801             }
5802             else if (!strncmp(temp, SERVER, strlen(SERVER)))
5803             {
5804                 if (strlen(temp) > (strlen(SERVER)))
5805                 {
5806                     ServerList[Count] = calloc(1, 256);
5807                     strcpy(ServerList[Count], &temp[strlen(SERVER)]);
5808                     StringTrim(ServerList[Count]);
5809                     ++Count;
5810                 }
5811             }
5812             else if (!strncmp(temp, MSSFU, strlen(MSSFU)))
5813             {
5814                 if (strlen(temp) > (strlen(MSSFU)))
5815                 {
5816                     strcpy(temp1, &temp[strlen(MSSFU)]);
5817                     StringTrim(temp1);
5818                     if (!strcmp(temp1, SFUTYPE))
5819                         UseSFU30 = 1;
5820                 }
5821             }
5822             else if (!strcasecmp(temp, "NOCHANGE"))
5823             {
5824                 NoChangeConfigFile = 1;
5825             }
5826             else
5827             {
5828                 if (strlen(ldap_domain) != 0)
5829                 {
5830                     memset(ldap_domain, '\0', sizeof(ldap_domain));
5831                     break;
5832                 }
5833                 if (strlen(temp) != 0)
5834                     strcpy(ldap_domain, temp);
5835             }
5836         }
5837         fclose(fptr);
5838     }
5839
5840     if (strlen(ldap_domain) == 0)
5841     {
5842       strcpy(ldap_domain, DomainName);
5843     }
5844     if (Count == 0)
5845         return(0);
5846     for (i = 0; i < Count; i++)
5847     {
5848         if (ServerList[i] != 0)
5849         {
5850             strcat(ServerList[i], ".");
5851             strcat(ServerList[i], ldap_domain);
5852             for (k = 0; k < (int)strlen(ServerList[i]); k++)
5853                 ServerList[i][k] = toupper(ServerList[i][k]);
5854         }
5855     }
5856     return(0);
5857 }
5858
5859 int ReadDomainList()
5860 {
5861   int     Count;
5862   int     i;
5863   char    temp[128];
5864   char    temp1[128];
5865   FILE    *fptr;
5866   unsigned char c[11];
5867   unsigned char stuff[256];
5868   int     rc;
5869   int     ok;
5870
5871   Count = 0;
5872   sprintf(temp, "%s%s", CFG_PATH, WINADCFG);
5873   if ((fptr = fopen(temp, "r")) != NULL)
5874     {
5875       while (fgets(temp, sizeof(temp), fptr) != 0)
5876         {
5877           for (i = 0; i < (int)strlen(temp); i++)
5878             temp[i] = toupper(temp[i]);
5879           if (temp[strlen(temp) - 1] == '\n')
5880             temp[strlen(temp) - 1] = '\0';
5881           StringTrim(temp);
5882           if (strlen(temp) == 0)
5883             continue;
5884           if (!strncmp(temp, DOMAIN, strlen(DOMAIN)))
5885             {
5886               if (strlen(temp) > (strlen(DOMAIN)))
5887                 {
5888                   strcpy(temp1, &temp[strlen(DOMAIN)]);
5889                   StringTrim(temp1);
5890                   strcpy(temp, temp1);
5891                 }
5892             }
5893           ok = 1;
5894           rc = sscanf(temp, "%c%c%c%c%c.%c%c%c.%c%c%c%s", &c[0],
5895                       &c[1], &c[2], &c[3], &c[4], &c[5], &c[6],
5896                       &c[7], &c[8], &c[9], &c[10], stuff);
5897           if (rc != 11)
5898             {
5899               rc = sscanf(temp, "%c%c%c%c.%c%c%c.%c%c%c%s", &c[0],
5900                           &c[1], &c[2], &c[3], &c[4], &c[5], &c[6],
5901                           &c[7], &c[8], &c[9], stuff);
5902               if (rc != 10)
5903                 {
5904                   rc = sscanf(temp, "%c%c%%c.%c%c%c.%c%c%c%s", &c[0],
5905                               &c[1], &c[2], &c[3], &c[4], &c[5],
5906                               &c[6], &c[7], &c[8], stuff);
5907                   if (rc != 9)
5908                     {
5909                       UpdateDomainList = 1;
5910                       ok = 0;
5911                     }
5912                 }
5913             }
5914           if (ok)
5915              {
5916                strcpy(DomainNames[Count], temp);
5917                StringTrim(DomainNames[Count]);
5918                ++Count;
5919              }
5920         }
5921       fclose(fptr);
5922     }
5923   if (Count == 0)
5924     {
5925       critical_alert("incremental", "%s",
5926                      "winad.incr cannot run due to a configuration error in winad.cfg");
5927       return(1);
5928     }
5929   return(0);
5930 }
5931
5932 void WriteDomainList()
5933 {
5934   char    temp[128];
5935   int     i;
5936   FILE    *fptr;
5937   
5938   sprintf(temp, "%s%s", CFG_PATH, WINADCFG);
5939   if ((fptr = fopen(temp, "w+")) != NULL)
5940     {
5941       for (i = 0; i < MAX_DOMAINS; i++)
5942         {
5943           if (strlen(DomainNames[i]) != 0)
5944             {
5945               fprintf(fptr, "%s\n", DomainNames[i]);
5946             }
5947         }
5948       fclose(fptr);
5949     }
5950 }
This page took 0.539503 seconds and 5 git commands to generate.