]> andersk Git - moira.git/blob - incremental/winad/winad.c
ffbf50afcc8e4c7083301298b24ff0b10d2de9ef
[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
1316 void do_user(LDAP *ldap_handle, char *dn_path, char *ldap_hostname, 
1317              char **before, int beforec, char **after, 
1318              int afterc)
1319 {
1320   int   rc;
1321   char  *av[7];
1322   char  after_user_id[32];
1323   char  before_user_id[32];
1324   char  *call_args[7];
1325
1326   if ((beforec == 0) && (afterc == 0))
1327     return;
1328
1329   memset(after_user_id, '\0', sizeof(after_user_id));
1330   memset(before_user_id, '\0', sizeof(before_user_id));
1331   if (beforec > U_USER_ID)
1332     strcpy(before_user_id, before[U_USER_ID]);
1333   if (afterc > U_USER_ID)
1334     strcpy(after_user_id, after[U_USER_ID]);
1335
1336   if ((beforec == 0) && (afterc == 0)) /*this case should never happen */
1337     return;
1338
1339   if ((beforec == 0) && (afterc != 0)) 
1340     {
1341       /*this case only happens when the account*/
1342       /*account is first created but not usable*/
1343       com_err(whoami, 0, "Unable to process user %s because the user account is not yet usable", after[U_NAME]);
1344       return;
1345     }
1346   if ((beforec != 0) && (afterc == 0)) /*this case only happens when the account*/
1347     {                                  /*is expunged*/
1348       if (atoi(before[U_STATE]) == 0)
1349         {
1350           com_err(whoami, 0, "expunging user %s from AD", before[U_NAME]);
1351           user_delete(ldap_handle, dn_path, before[U_NAME], before_user_id);
1352         }
1353       else
1354         {
1355           com_err(whoami, 0, "Unable to process because user %s has been previously expungeded", before[U_NAME]);
1356         }
1357       return;
1358     }
1359
1360   /*process anything that gets here*/
1361   if ((rc = check_user(ldap_handle, dn_path, before[U_NAME], 
1362                        before_user_id)) == AD_NO_USER_FOUND)
1363     {
1364       if (!check_string(after[U_NAME]))
1365         return;
1366       if (rc = moira_connect())
1367         {
1368           critical_alert("AD incremental", 
1369                          "Error connection to Moira : %s",
1370                          error_message(rc));
1371           return;
1372         }
1373       com_err(whoami, 0, "creating user %s", after[U_NAME]);
1374
1375       av[0] = after[U_NAME];
1376       call_args[0] = (char *)ldap_handle;
1377       call_args[1] = dn_path;
1378       call_args[2] = after_user_id;
1379       call_args[3] = NULL;
1380       callback_rc = 0;
1381       if (rc = mr_query("get_user_account_by_login", 1, av, user_create,
1382                         call_args))
1383         {
1384           moira_disconnect();
1385           com_err(whoami, 0, "Unable to create user %s : %s",
1386                   after[U_NAME], error_message(rc));
1387           return;
1388         }
1389       if (callback_rc)
1390         {
1391           moira_disconnect();
1392           com_err(whoami, 0, "Unable to create user %s", after[U_NAME]);
1393           return;
1394         }
1395       return;
1396     }
1397   else
1398     {
1399       if (rc != 0)
1400         return;
1401     }
1402   if (strcmp(before[U_NAME], after[U_NAME]))
1403     {
1404       if ((check_string(before[U_NAME])) && (check_string(after[U_NAME])))
1405         {
1406           com_err(whoami, 0, "changing user %s to %s", 
1407                   before[U_NAME], after[U_NAME]);
1408           if ((rc = user_rename(ldap_handle, dn_path, before[U_NAME], 
1409                                 after[U_NAME])) != LDAP_SUCCESS)
1410             {
1411               return;
1412             }
1413         }
1414     }
1415   com_err(whoami, 0, "updating user %s information", after[U_NAME]);
1416   rc = user_update(ldap_handle, dn_path, after[U_NAME],
1417                    after[U_UID], after[U_MITID], 
1418                    after_user_id, atoi(after[U_STATE]),
1419                    after[U_HOMEDIR], after[U_PROFILEDIR]);
1420   return;
1421 }
1422
1423 int construct_newvalues(LK_ENTRY *linklist_base, int modvalue_count, 
1424                         char *oldValue, char *newValue,
1425                         char ***modvalues, int type)
1426 {
1427   LK_ENTRY    *linklist_ptr;
1428   int         i;
1429   char        *cPtr;
1430
1431   if (((*modvalues) = calloc(1, (modvalue_count + 1) * sizeof(char *)))
1432       == NULL)
1433     {
1434       return(1);
1435     }
1436   for (i = 0; i < (modvalue_count + 1); i++)
1437     (*modvalues)[i] = NULL;
1438   if (modvalue_count != 0)
1439     {
1440       linklist_ptr = linklist_base;
1441       for (i = 0; i < modvalue_count; i++)
1442         {
1443           if ((oldValue != NULL) && (newValue != NULL))
1444             {
1445               if ((cPtr = (char *)strstr(linklist_ptr->value, oldValue))
1446                  != (char *)NULL)
1447                 {
1448                   if (type == REPLACE)
1449                     {
1450                       if (((*modvalues)[i] = calloc(1, strlen(newValue) + 1))
1451                           == NULL)
1452                         return(1);
1453                       memset((*modvalues)[i], '\0', strlen(newValue) + 1);
1454                       strcpy((*modvalues)[i], newValue);
1455                     }
1456                   else
1457                     {
1458                       if (((*modvalues)[i] = calloc(1, 
1459                                         (int)(cPtr - linklist_ptr->value) + 
1460                                         (linklist_ptr->length - strlen(oldValue)) + 
1461                                         strlen(newValue) + 1)) == NULL)
1462                         return(1);
1463                       memset((*modvalues)[i], '\0', 
1464                              (int)(cPtr - linklist_ptr->value) + 
1465                              (linklist_ptr->length - strlen(oldValue)) + 
1466                              strlen(newValue) + 1);
1467                       memcpy((*modvalues)[i], linklist_ptr->value, 
1468                              (int)(cPtr - linklist_ptr->value));
1469                       strcat((*modvalues)[i], newValue);
1470                       strcat((*modvalues)[i], 
1471      &linklist_ptr->value[(int)(cPtr - linklist_ptr->value) + strlen(oldValue)]);
1472                     }
1473                 }
1474               else
1475                 {
1476                   (*modvalues)[i] = calloc(1, linklist_ptr->length + 1);
1477                   memset((*modvalues)[i], '\0', linklist_ptr->length + 1);
1478                   memcpy((*modvalues)[i], linklist_ptr->value,
1479                          linklist_ptr->length);
1480                 }
1481             }
1482         else
1483             {
1484               (*modvalues)[i] = calloc(1, linklist_ptr->length + 1);
1485               memset((*modvalues)[i], '\0', linklist_ptr->length + 1);
1486               memcpy((*modvalues)[i], linklist_ptr->value,
1487                      linklist_ptr->length);
1488             }
1489           linklist_ptr = linklist_ptr->next;
1490         }
1491       (*modvalues)[i] = NULL;
1492     }
1493   return(0);
1494 }
1495
1496
1497 int linklist_build(LDAP *ldap_handle, char *dn_path, char *search_exp, 
1498                    char **attr_array, LK_ENTRY **linklist_base,
1499                    int *linklist_count, unsigned long ScopeType)
1500 {
1501   ULONG       rc;
1502   LDAPMessage *ldap_entry;
1503
1504   rc = 0;
1505   ldap_entry = NULL;
1506   (*linklist_base) = NULL;
1507   (*linklist_count) = 0;
1508   if ((rc = ldap_search_s(ldap_handle, dn_path, ScopeType, 
1509                           search_exp, attr_array, 0, &ldap_entry))
1510       != LDAP_SUCCESS)
1511       {
1512         if (rc != LDAP_SIZELIMIT_EXCEEDED)
1513           return(0);
1514       }
1515
1516   rc = retrieve_entries(ldap_handle, ldap_entry, linklist_base, linklist_count);
1517
1518   ldap_msgfree(ldap_entry);
1519   return(rc);
1520 }
1521
1522
1523 int retrieve_entries(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
1524                      LK_ENTRY **linklist_base, int *linklist_count)
1525 {
1526   char        distinguished_name[1024];
1527   LK_ENTRY    *linklist_ptr;
1528   int         rc;
1529
1530   if ((ldap_entry = ldap_first_entry(ldap_handle, ldap_entry)) == NULL)
1531     return(0);
1532
1533   memset(distinguished_name, '\0', sizeof(distinguished_name));
1534   get_distinguished_name(ldap_handle, ldap_entry, distinguished_name);
1535
1536   if ((rc = retrieve_attributes(ldap_handle, ldap_entry, distinguished_name,
1537                                 linklist_base)) != 0)
1538     return(rc);
1539
1540   while ((ldap_entry = ldap_next_entry(ldap_handle, ldap_entry)) != NULL)
1541     {
1542       memset(distinguished_name, '\0', sizeof(distinguished_name));
1543       get_distinguished_name(ldap_handle, ldap_entry, distinguished_name);
1544
1545       if ((rc = retrieve_attributes(ldap_handle, ldap_entry, distinguished_name,
1546                                     linklist_base)) != 0)
1547         return(rc);
1548     }
1549
1550   linklist_ptr = (*linklist_base);
1551   (*linklist_count) = 0;
1552   while (linklist_ptr != NULL)
1553     {
1554       ++(*linklist_count);
1555       linklist_ptr = linklist_ptr->next;
1556     }
1557   return(0);
1558 }
1559
1560 int retrieve_attributes(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
1561                         char *distinguished_name, LK_ENTRY **linklist_current)
1562 {
1563   char        *Attribute;
1564   BerElement  *ptr;
1565
1566   ptr = NULL;
1567   if ((Attribute = ldap_first_attribute(ldap_handle, ldap_entry, &ptr)) != NULL)
1568     {
1569       retrieve_values(ldap_handle, ldap_entry, Attribute, distinguished_name,
1570                       linklist_current);
1571       ldap_memfree(Attribute);
1572       while ((Attribute = ldap_next_attribute(ldap_handle, ldap_entry, 
1573                                               ptr)) != NULL)
1574         {
1575           retrieve_values(ldap_handle, ldap_entry, Attribute,
1576                           distinguished_name, linklist_current);
1577           ldap_memfree(Attribute);
1578         }
1579     }
1580   ldap_ber_free(ptr, 0);
1581   return(0);
1582 }
1583
1584 int retrieve_values(LDAP *ldap_handle, LDAPMessage *ldap_entry,
1585                     char *Attribute, char *distinguished_name,
1586                     LK_ENTRY **linklist_current)
1587 {
1588   char        **str_value;
1589   char        temp[256];
1590   void        **Ptr;
1591   int         use_bervalue;
1592   LK_ENTRY    *linklist_previous;
1593   LDAP_BERVAL **ber_value;
1594   DWORD       ber_length;
1595 #ifdef LDAP_DEBUG
1596   SID         *sid;
1597   GUID        *guid;
1598   int         i;
1599   int         intValue;
1600   DWORD       *subauth;
1601   SID_IDENTIFIER_AUTHORITY    *sid_auth;
1602   unsigned char   *subauth_count;
1603 #endif /*LDAP_BEGUG*/
1604
1605   use_bervalue = 0;
1606   memset(temp, '\0', sizeof(temp));
1607   if ((!strcmp(Attribute, "objectSid")) ||
1608       (!strcmp(Attribute, "objectGUID")))
1609     use_bervalue = 1;
1610
1611   if (use_bervalue)
1612     {
1613       ber_value = ldap_get_values_len(ldap_handle, ldap_entry, Attribute);
1614       Ptr = (void **)ber_value;
1615       str_value = NULL;
1616       }
1617   else
1618     {
1619       str_value = ldap_get_values(ldap_handle, ldap_entry, Attribute);
1620       Ptr = (void **)str_value;
1621       ber_value = NULL;
1622     }
1623   if (Ptr != NULL)
1624     {
1625       for (; *Ptr; Ptr++) 
1626         {
1627           if ((linklist_previous = calloc(1, sizeof(LK_ENTRY))) == NULL)
1628             return(1);
1629           memset(linklist_previous, '\0', sizeof(LK_ENTRY));
1630           linklist_previous->next = (*linklist_current);
1631           (*linklist_current) = linklist_previous;
1632
1633           if (((*linklist_current)->attribute = calloc(1, 
1634                                                strlen(Attribute) + 1)) == NULL)
1635             return(1);
1636           memset((*linklist_current)->attribute, '\0', strlen(Attribute) + 1);
1637           strcpy((*linklist_current)->attribute, Attribute);
1638           if (use_bervalue)
1639             {
1640               ber_length = (*(LDAP_BERVAL **)Ptr)->bv_len;
1641               if (((*linklist_current)->value = calloc(1, ber_length)) == NULL)
1642                 return(1);
1643               memset((*linklist_current)->value, '\0', ber_length);
1644               memcpy((*linklist_current)->value, (*(LDAP_BERVAL **)Ptr)->bv_val, 
1645                                                   ber_length);
1646               (*linklist_current)->length = ber_length;
1647             }
1648           else
1649             {
1650               if (((*linklist_current)->value = calloc(1, 
1651                                                   strlen(*Ptr) + 1)) == NULL)
1652                 return(1);
1653               memset((*linklist_current)->value, '\0', strlen(*Ptr) + 1);
1654               (*linklist_current)->length = strlen(*Ptr);
1655               strcpy((*linklist_current)->value, *Ptr);
1656             }
1657           (*linklist_current)->ber_value = use_bervalue;
1658           if (((*linklist_current)->dn = calloc(1, 
1659                                       strlen(distinguished_name) + 1)) == NULL)
1660             return(1);
1661           memset((*linklist_current)->dn, '\0', strlen(distinguished_name) + 1);
1662           strcpy((*linklist_current)->dn, distinguished_name);
1663
1664 #ifdef LDAP_DEBUG
1665           if (!strcmp(Attribute, "objectGUID"))
1666             {
1667               guid = (GUID *)((*linklist_current)->value);
1668               sprintf(temp, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 
1669                       guid->Data1, guid->Data2, guid->Data3, 
1670                       guid->Data4[0], guid->Data4[1], guid->Data4[2], 
1671                       guid->Data4[3], guid->Data4[4], guid->Data4[5], 
1672                       guid->Data4[6], guid->Data4[7]);
1673               print_to_screen("     %20s : {%s}\n", Attribute, temp);
1674             }
1675           else if (!strcmp(Attribute, "objectSid"))
1676             {
1677               sid = (SID *)((*(LDAP_BERVAL **)Ptr)->bv_val);
1678 #ifdef _WIN32
1679               print_to_screen("        Revision = %d\n", sid->Revision);
1680               print_to_screen("        SID Identifier Authority:\n");
1681               sid_auth = &sid->IdentifierAuthority;
1682               if (sid_auth->Value[0])
1683                 print_to_screen("            SECURITY_NULL_SID_AUTHORITY\n");
1684               else if (sid_auth->Value[1])
1685                 print_to_screen("            SECURITY_WORLD_SID_AUTHORITY\n");
1686               else if (sid_auth->Value[2])
1687                 print_to_screen("            SECURITY_LOCAL_SID_AUTHORITY\n");
1688               else if (sid_auth->Value[3])
1689                 print_to_screen("            SECURITY_CREATOR_SID_AUTHORITY\n");
1690               else if (sid_auth->Value[5])
1691                 print_to_screen("            SECURITY_NT_AUTHORITY\n");
1692               else
1693                 print_to_screen("            UNKNOWN SID AUTHORITY\n");
1694               subauth_count = GetSidSubAuthorityCount(sid);
1695               print_to_screen("        SidSubAuthorityCount = %d\n", 
1696                               *subauth_count);
1697               print_to_screen("        SidSubAuthority:\n");
1698               for (i = 0; i < *subauth_count; i++)
1699                 {
1700                   if ((subauth = GetSidSubAuthority(sid, i)) != NULL)
1701                     print_to_screen("            %u\n", *subauth);
1702                 }
1703 #endif
1704             }
1705           else if ((!memcmp(Attribute, "userAccountControl", 
1706                             strlen("userAccountControl"))) ||
1707                    (!memcmp(Attribute, "sAMAccountType", 
1708                             strlen("sAmAccountType"))))
1709             {
1710               intValue = atoi(*Ptr);
1711               print_to_screen("     %20s : %ld\n",Attribute, intValue);
1712               if (!memcmp(Attribute, "userAccountControl", 
1713                           strlen("userAccountControl")))
1714                 {
1715                   if (intValue & UF_ACCOUNTDISABLE)
1716                     print_to_screen("     %20s :    %s\n", 
1717                                     "", "Account disabled");
1718                   else
1719                     print_to_screen("     %20s :    %s\n", 
1720                                     "", "Account active");
1721                   if (intValue & UF_HOMEDIR_REQUIRED)
1722                     print_to_screen("     %20s :    %s\n", 
1723                                     "", "Home directory required");
1724                   if (intValue & UF_LOCKOUT)
1725                     print_to_screen("     %20s :    %s\n", 
1726                                     "", "Account locked out");
1727                   if (intValue & UF_PASSWD_NOTREQD)
1728                     print_to_screen("     %20s :    %s\n", 
1729                                     "", "No password required");
1730                   if (intValue & UF_PASSWD_CANT_CHANGE)
1731                     print_to_screen("     %20s :    %s\n",
1732                                     "", "Cannot change password");
1733                   if (intValue & UF_TEMP_DUPLICATE_ACCOUNT)
1734                     print_to_screen("     %20s :    %s\n", 
1735                                     "", "Temp duplicate account");
1736                   if (intValue & UF_NORMAL_ACCOUNT)
1737                     print_to_screen("     %20s :    %s\n", 
1738                                     "", "Normal account");
1739                   if (intValue & UF_INTERDOMAIN_TRUST_ACCOUNT)
1740                     print_to_screen("     %20s :    %s\n", 
1741                                     "", "Interdomain trust account");
1742                   if (intValue & UF_WORKSTATION_TRUST_ACCOUNT)
1743                     print_to_screen("     %20s :    %s\n", 
1744                                     "", "Workstation trust account");
1745                   if (intValue & UF_SERVER_TRUST_ACCOUNT)
1746                     print_to_screen("     %20s :    %s\n", 
1747                                     "", "Server trust account");
1748                 }
1749             }
1750           else
1751             {
1752               print_to_screen("     %20s : %s\n",Attribute, *Ptr);
1753             }
1754 #endif /*LDAP_DEBUG*/
1755         }
1756       if (str_value != NULL)
1757         ldap_value_free(str_value);
1758       if (ber_value != NULL)
1759         ldap_value_free_len(ber_value);
1760     }
1761   (*linklist_current) = linklist_previous;
1762   return(0);
1763 }
1764
1765 int moira_connect(void)
1766 {
1767   long    rc;
1768   char    HostName[64];
1769
1770   if (!mr_connections++)
1771     {
1772 #ifdef _WIN32
1773       memset(HostName, '\0', sizeof(HostName));
1774       strcpy(HostName, "ttsp");
1775       rc = mr_connect_cl(HostName, "winad.incr", QUERY_VERSION, 1);
1776 /*det
1777       rc = mr_connect(HostName);
1778 */
1779 #else
1780       struct utsname uts;
1781       uname(&uts);
1782       rc = mr_connect_cl(uts.nodename, "winad.incr", QUERY_VERSION, 1);
1783 /*
1784       rc = mr_connect(uts.nodename);
1785 */
1786 #endif /*WIN32*/
1787 /*det
1788       if (!rc)
1789         rc = mr_krb5_auth("winad.incr");
1790 */
1791       return rc;
1792     }
1793   return 0;
1794 }
1795
1796 int check_winad(void)
1797 {
1798   int i;
1799   
1800   for (i = 0; file_exists(STOP_FILE); i++)
1801     {
1802       if (i > 30)
1803         {
1804           critical_alert("AD incremental",
1805                          "WINAD incremental failed (%s exists): %s",
1806                          STOP_FILE, tbl_buf);
1807           return(1);
1808         }
1809       sleep(60);
1810     }
1811   return(0);
1812 }
1813
1814 int moira_disconnect(void)
1815 {
1816
1817   if (!--mr_connections)
1818     {
1819       mr_disconnect();
1820     }
1821   return 0;
1822 }
1823
1824 void get_distinguished_name(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
1825                             char *distinguished_name)
1826 {
1827   char    *CName;
1828
1829   CName = ldap_get_dn(ldap_handle, ldap_entry);
1830   if (CName == NULL)
1831     return;
1832   strcpy(distinguished_name, CName);
1833   ldap_memfree(CName);
1834 }
1835
1836 int linklist_create_entry(char *attribute, char *value, 
1837                           LK_ENTRY **linklist_entry)
1838 {
1839   (*linklist_entry) = calloc(1, sizeof(LK_ENTRY));
1840   if (!(*linklist_entry))
1841     {
1842       return(1);
1843     }
1844   memset((*linklist_entry), '\0', sizeof(LK_ENTRY));
1845   (*linklist_entry)->attribute = calloc(1, strlen(attribute) + 1);
1846   memset((*linklist_entry)->attribute, '\0', strlen(attribute) + 1);
1847   strcpy((*linklist_entry)->attribute, attribute);
1848   (*linklist_entry)->value = calloc(1, strlen(value) + 1);
1849   memset((*linklist_entry)->value, '\0', strlen(value) + 1);
1850   strcpy((*linklist_entry)->value, value);
1851   (*linklist_entry)->length = strlen(value);
1852   (*linklist_entry)->next = NULL;
1853   return(0);
1854 }
1855
1856 void print_to_screen(const char *fmt, ...)
1857 {
1858   va_list pvar;
1859
1860   va_start(pvar, fmt);
1861   vfprintf(stderr, fmt, pvar);
1862   fflush(stderr);
1863   va_end(pvar);
1864 }
1865
1866 int get_group_membership(char *group_membership, char *group_ou, 
1867                          int *security_flag, char **av)
1868 {
1869   int  maillist_flag;
1870   int  group_flag;
1871
1872   maillist_flag = atoi(av[L_MAILLIST]);
1873   group_flag = atoi(av[L_GROUP]);
1874   if (security_flag != NULL)
1875     (*security_flag) = 0;
1876
1877   if ((maillist_flag) && (group_flag))
1878     {
1879       if (group_membership != NULL)
1880         group_membership[0] = 'B';
1881       if (security_flag != NULL)
1882         (*security_flag) = 1;
1883       if (group_ou != NULL)
1884         strcpy(group_ou, group_ou_both);
1885     }
1886   else if ((!maillist_flag) && (group_flag))
1887     {
1888       if (group_membership != NULL)
1889         group_membership[0] = 'S';
1890       if (security_flag != NULL)
1891         (*security_flag) = 1;
1892       if (group_ou != NULL)
1893         strcpy(group_ou, group_ou_security);
1894     }
1895   else if ((maillist_flag) && (!group_flag))
1896     {
1897       if (group_membership != NULL)
1898         group_membership[0] = 'D';
1899       if (group_ou != NULL)
1900         strcpy(group_ou, group_ou_distribution);
1901     }
1902   else
1903     {
1904       if (group_membership != NULL)
1905         group_membership[0] = 'N';
1906       if (group_ou != NULL)
1907         strcpy(group_ou, group_ou_neither);
1908     }
1909   return(0);
1910 }
1911
1912 int group_rename(LDAP *ldap_handle, char *dn_path, 
1913                  char *before_group_name, char *before_group_membership, 
1914                  char *before_group_ou, int before_security_flag, char *before_desc,
1915                  char *after_group_name, char *after_group_membership, 
1916                  char *after_group_ou, int after_security_flag, char *after_desc,
1917                  char *MoiraId, char *filter)
1918 {
1919   LDAPMod   *mods[20];
1920   char      old_dn[512];
1921   char      new_dn[512];
1922   char      new_dn_path[512];
1923   char      sam_name[256];
1924   char      *attr_array[3];
1925   char      *mitMoiraId_v[] = {NULL, NULL};
1926   char      *name_v[] = {NULL, NULL};
1927   char      *samAccountName_v[] = {NULL, NULL};
1928   char      *groupTypeControl_v[] = {NULL, NULL};
1929   u_int     groupTypeControl = ADS_GROUP_TYPE_GLOBAL_GROUP;
1930   char      groupTypeControlStr[80];
1931   int       n;
1932   int       i;
1933   int       rc;
1934   LK_ENTRY  *group_base;
1935   int       group_count;
1936
1937   if (!check_string(before_group_name))
1938     {
1939       com_err(whoami, 0, "Unable to process invalid LDAP list name %s", before_group_name);
1940       return(AD_INVALID_NAME);
1941     }
1942   if (!check_string(after_group_name))
1943     {
1944       com_err(whoami, 0, "Unable to process invalid LDAP list name %s", after_group_name);
1945       return(AD_INVALID_NAME);
1946     }
1947
1948   group_count = 0;
1949   group_base = NULL;
1950   if (rc = ad_get_group(ldap_handle, dn_path, before_group_name, 
1951                         before_group_membership, 
1952                         MoiraId, "distinguishedName", &group_base, 
1953                         &group_count, filter))
1954     return(rc);
1955
1956   if (group_count == 0)
1957     {
1958       return(AD_NO_GROUPS_FOUND);
1959     }
1960   if (group_count != 1)
1961     {
1962       com_err(whoami, 0,
1963               "Unable to process multiple groups with MoiraId = %s exist in the AD",
1964               MoiraId);
1965       return(AD_MULTIPLE_GROUPS_FOUND);
1966     }
1967   strcpy(old_dn, group_base->value);
1968
1969   linklist_free(group_base);
1970   group_base = NULL;
1971   group_count = 0;
1972   attr_array[0] = "sAMAccountName";
1973   attr_array[1] = NULL;
1974   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
1975                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
1976     {
1977       com_err(whoami, 0, "Unable to get list %s dn : %s",
1978               after_group_name, ldap_err2string(rc));
1979       return(rc);
1980     }
1981   if (group_count != 1)
1982     {
1983       com_err(whoami, 0,
1984               "Unable to get sAMAccountName for group %s", 
1985               before_group_name);
1986       return(AD_LDAP_FAILURE);
1987     }
1988
1989   strcpy(sam_name, group_base->value);
1990   linklist_free(group_base);
1991   group_base = NULL;
1992   group_count = 0;
1993
1994   sprintf(new_dn_path, "%s,%s", after_group_ou, dn_path);
1995   sprintf(new_dn, "cn=%s", after_group_name);
1996   if ((rc = ldap_rename_s(ldap_handle, old_dn, new_dn, new_dn_path,
1997                           TRUE, NULL, NULL)) != LDAP_SUCCESS)
1998     {
1999       com_err(whoami, 0, "Unable to rename list from %s to %s : %s",
2000               before_group_name, after_group_name, ldap_err2string(rc));
2001       return(rc);
2002     }
2003
2004   name_v[0] = after_group_name;
2005   if (!strncmp(&sam_name[strlen(sam_name) - strlen("_group")], "_group", strlen("_group")))
2006     {
2007       sprintf(sam_name, "%s_group", after_group_name);
2008     }
2009   else
2010     {
2011       com_err(whoami, 0, "Unable to rename list from %s to %s : sAMAccountName not found",
2012               before_group_name, after_group_name);
2013       return(rc);
2014     }
2015   samAccountName_v[0] = sam_name;
2016   if (after_security_flag)
2017     groupTypeControl |= ADS_GROUP_TYPE_SECURITY_ENABLED;
2018   sprintf(groupTypeControlStr, "%ld", groupTypeControl);
2019   groupTypeControl_v[0] = groupTypeControlStr;
2020   mitMoiraId_v[0] = MoiraId;
2021
2022   sprintf(new_dn, "cn=%s,%s,%s", after_group_name, after_group_ou, dn_path);
2023   rc = attribute_update(ldap_handle, new_dn, after_desc, "description", after_group_name);
2024   n = 0;
2025   ADD_ATTR("samAccountName", samAccountName_v, LDAP_MOD_REPLACE);
2026   ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
2027   ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
2028   ADD_ATTR("groupType", groupTypeControl_v, LDAP_MOD_REPLACE);
2029   mods[n] = NULL;
2030   if ((rc = ldap_modify_s(ldap_handle, new_dn, mods)) != LDAP_SUCCESS)
2031     {
2032       com_err(whoami, 0, "Unable to modify list data for %s after renaming: %s",
2033               after_group_name, ldap_err2string(rc));
2034     }
2035   for (i = 0; i < n; i++)
2036     free(mods[i]);
2037   return(rc);
2038 }
2039
2040 int group_create(int ac, char **av, void *ptr)
2041 {
2042   LDAPMod *mods[20];
2043   char new_dn[256];
2044   char group_ou[256];
2045   char new_group_name[256];
2046   char sam_group_name[256];
2047   char cn_group_name[256];
2048   char *cn_v[] = {NULL, NULL};
2049   char *objectClass_v[] = {"top", "group", NULL};
2050   char info[256];
2051   char *samAccountName_v[] = {NULL, NULL};
2052   char *altSecurityIdentities_v[] = {NULL, NULL};
2053   char *member_v[] = {NULL, NULL};
2054   char *name_v[] = {NULL, NULL};
2055   char *desc_v[] = {NULL, NULL};
2056   char *info_v[] = {NULL, NULL};
2057   char *mitMoiraId_v[] = {NULL, NULL};
2058   char *groupTypeControl_v[] = {NULL, NULL};
2059   char groupTypeControlStr[80];
2060   char group_membership[1];
2061   int  i;
2062   int  security_flag;
2063   u_int groupTypeControl = ADS_GROUP_TYPE_GLOBAL_GROUP;
2064   int  n;
2065   int  rc;
2066   int  updateGroup;
2067   char **call_args;
2068
2069   call_args = ptr;
2070
2071   if (!check_string(av[L_NAME]))
2072     {
2073       com_err(whoami, 0, "Unable to process invalid LDAP list name %s", av[L_NAME]);
2074       return(AD_INVALID_NAME);
2075     }
2076
2077   updateGroup = (int)call_args[4];
2078   memset(group_ou, 0, sizeof(group_ou));
2079   memset(group_membership, 0, sizeof(group_membership));
2080   security_flag = 0;
2081   get_group_membership(group_membership, group_ou, &security_flag, av);
2082   strcpy(new_group_name, av[L_NAME]);
2083   sprintf(new_dn, "cn=%s,%s,%s", new_group_name, group_ou, call_args[1]);
2084   if (security_flag)
2085     groupTypeControl |= ADS_GROUP_TYPE_SECURITY_ENABLED;
2086   
2087   sprintf(sam_group_name, "%s_group", av[L_NAME]);
2088
2089   if (!updateGroup)
2090     {
2091
2092       sprintf(groupTypeControlStr, "%ld", groupTypeControl);
2093       groupTypeControl_v[0] = groupTypeControlStr;
2094
2095       strcpy(cn_group_name, av[L_NAME]);
2096
2097       samAccountName_v[0] = sam_group_name;
2098       name_v[0] = new_group_name;
2099       cn_v[0] = new_group_name;
2100
2101       n = 0;
2102       ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
2103       ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2104       ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
2105       ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2106       ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2107       if (strlen(av[L_DESC]) != 0)
2108         {
2109           desc_v[0] = av[L_DESC];
2110           ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2111         }
2112       ADD_ATTR("groupType", groupTypeControl_v, LDAP_MOD_ADD);
2113       if (strlen(av[L_ACE_NAME]) != 0)
2114         {
2115           sprintf(info, "The Administrator of this list is: %s", av[L_ACE_NAME]);
2116           info_v[0] = info;
2117           ADD_ATTR("info", info_v, LDAP_MOD_ADD);
2118         }
2119       if (strlen(call_args[5]) != 0)
2120         {
2121           mitMoiraId_v[0] = call_args[5];
2122           ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_ADD);
2123         }
2124       mods[n] = NULL;
2125
2126       rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
2127
2128       for (i = 0; i < n; i++)
2129         free(mods[i]);
2130       if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2131         {
2132           com_err(whoami, 0, "Unable to create list %s in AD : %s",
2133                   av[L_NAME], ldap_err2string(rc));
2134           callback_rc = rc;
2135           return(rc);
2136         }
2137     }
2138   if ((rc == LDAP_ALREADY_EXISTS) || (updateGroup))
2139     {
2140       rc = attribute_update((LDAP *)call_args[0], new_dn, av[L_DESC], "description", av[L_NAME]);
2141       sprintf(info, "The Administrator of this list is: %s", av[L_ACE_NAME]);
2142       rc = attribute_update((LDAP *)call_args[0], new_dn, info, "info", av[L_NAME]);
2143       n = 0;
2144       if (strlen(call_args[5]) != 0)
2145         {
2146           mitMoiraId_v[0] = call_args[5];
2147           ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
2148         }
2149       if (!(atoi(av[L_ACTIVE])))
2150         {
2151           member_v[0] = NULL;
2152           ADD_ATTR("member", member_v, LDAP_MOD_REPLACE);
2153         }
2154       mods[n] = NULL;
2155       rc = LDAP_SUCCESS;
2156       if (n != 0)
2157         {
2158           rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
2159           for (i = 0; i < n; i++)
2160               free(mods[i]);
2161           if (rc != LDAP_SUCCESS)
2162             {
2163               com_err(whoami, 0, "Unable to update list %s in AD : %s",
2164                       av[L_NAME], ldap_err2string(rc));
2165               callback_rc = rc;
2166               return(rc);
2167             }
2168         }
2169     }
2170
2171   ProcessGroupSecurity((LDAP *)call_args[0], call_args[1], av[L_NAME], 
2172                        atoi(av[L_HIDDEN]),  av[L_ACE_TYPE], av[L_ACE_NAME]);
2173
2174   return(LDAP_SUCCESS);
2175 }
2176
2177 int ProcessGroupSecurity(LDAP *ldap_handle, char *dn_path, char *TargetGroupName, 
2178                          int HiddenGroup, char *AceType, char *AceName)
2179 {
2180   char          filter_exp[1024];
2181   char          *attr_array[5];
2182   char          search_path[512];
2183   char          root_ou[128];
2184   char          TemplateDn[512];
2185   char          TemplateSamName[128];
2186   char          TargetDn[512];
2187   char          TargetSamName[128];
2188   char          AceSamAccountName[128];
2189   char          AceDn[256];
2190   unsigned char AceSid[128];
2191   unsigned char UserTemplateSid[128];
2192   char          acBERBuf[N_SD_BER_BYTES];
2193   char          GroupSecurityTemplate[256];
2194   int           AceSidCount;
2195   int           UserTemplateSidCount;
2196   int           group_count;
2197   int           n;
2198   int           i;
2199   int           rc;
2200   int           nVal;
2201   ULONG         dwInfo;
2202   int           array_count = 0;
2203   LDAPMod       *mods[20];
2204   LK_ENTRY      *group_base;
2205   LDAP_BERVAL   **ppsValues;
2206   LDAPControl sControl = {"1.2.840.113556.1.4.801",
2207                           { N_SD_BER_BYTES, acBERBuf },
2208                           TRUE
2209                          };
2210   LDAPControl *apsServerControls[] = {&sControl, NULL};
2211   LDAPMessage *psMsg;
2212
2213   dwInfo = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;
2214   BEREncodeSecurityBits(dwInfo, acBERBuf);
2215
2216   sprintf(search_path, "%s,%s", group_ou_root, dn_path);
2217   sprintf(filter_exp, "(sAMAccountName=%s_group)", TargetGroupName);
2218   attr_array[0] = "sAMAccountName";
2219   attr_array[1] = NULL;
2220   group_count = 0;
2221   group_base = NULL;
2222   if ((rc = linklist_build(ldap_handle, search_path, filter_exp, attr_array, 
2223                                &group_base, &group_count, LDAP_SCOPE_SUBTREE) != 0))
2224     return(1);
2225   if (group_count != 1)
2226     {
2227       linklist_free(group_base);
2228       return(1);
2229     }
2230   strcpy(TargetDn, group_base->dn);
2231   strcpy(TargetSamName, group_base->value);
2232   linklist_free(group_base);
2233   group_base = NULL;
2234   group_count = 0;
2235
2236   UserTemplateSidCount = 0;
2237   memset(UserTemplateSid, '\0', sizeof(UserTemplateSid));
2238   memset(AceSamAccountName, '\0', sizeof(AceSamAccountName));
2239   memset(AceSid, '\0', sizeof(AceSid));
2240   AceSidCount = 0;
2241   group_base = NULL;
2242   group_count = 0;
2243   if (strlen(AceName) != 0)
2244     {
2245       if (!strcmp(AceType, "LIST"))
2246         {
2247           sprintf(AceSamAccountName, "%s_group", AceName);
2248           strcpy(root_ou, group_ou_root);
2249         }
2250       else if (!strcmp(AceType, "USER"))
2251         {
2252           sprintf(AceSamAccountName, "%s", AceName);
2253           strcpy(root_ou, user_ou);
2254         }
2255       if (strlen(AceSamAccountName) != 0)
2256         {
2257           sprintf(search_path, "%s", dn_path);
2258           sprintf(filter_exp, "(sAMAccountName=%s)", AceSamAccountName);
2259           attr_array[0] = "objectSid";
2260           attr_array[1] = NULL;
2261           group_count = 0;
2262           group_base = NULL;
2263           if ((rc = linklist_build(ldap_handle, search_path, filter_exp, attr_array, 
2264                                    &group_base, &group_count, LDAP_SCOPE_SUBTREE) != 0))
2265             return(1);
2266           if (group_count == 1)
2267             {
2268               strcpy(AceDn, group_base->dn);
2269               AceSidCount = group_base->length;
2270               memcpy(AceSid, group_base->value, AceSidCount);
2271             }
2272           linklist_free(group_base);
2273           group_base = NULL;
2274           group_count = 0;
2275         }
2276     }
2277   if (AceSidCount == 0)
2278     {
2279       com_err(whoami, 0, "Group %s: Administrator: %s, Type: %s - does not have an AD SID.", TargetGroupName, AceName, AceType);
2280       com_err(whoami, 0, "   Non-admin security group template will be used.");
2281     }
2282   else
2283     {
2284       sprintf(search_path, "%s,%s", security_template_ou, dn_path);
2285       sprintf(filter_exp, "(sAMAccountName=%s)", "UserTemplate.u");
2286       attr_array[0] = "objectSid";
2287       attr_array[1] = NULL;
2288
2289       group_count = 0;
2290       group_base = NULL;
2291       if ((rc = linklist_build(ldap_handle, search_path, filter_exp, attr_array, 
2292                                    &group_base, &group_count, LDAP_SCOPE_SUBTREE) != 0))
2293         return(1);
2294       if ((rc != 0) || (group_count != 1))
2295         {
2296           com_err(whoami, 0, "Unable to process user security template: %s", "UserTemplate");
2297           AceSidCount = 0;
2298         }
2299       else
2300         {
2301           UserTemplateSidCount = group_base->length;
2302           memcpy(UserTemplateSid, group_base->value, UserTemplateSidCount);
2303         }
2304       linklist_free(group_base);
2305       group_base = NULL;
2306       group_count = 0;
2307     }
2308
2309   if (HiddenGroup)
2310     {
2311       if (AceSidCount == 0)
2312         {
2313           strcpy(GroupSecurityTemplate, HIDDEN_GROUP);
2314           sprintf(filter_exp, "(sAMAccountName=%s)", HIDDEN_GROUP);
2315         }
2316       else
2317         {
2318           strcpy(GroupSecurityTemplate, HIDDEN_GROUP_WITH_ADMIN);
2319           sprintf(filter_exp, "(sAMAccountName=%s)", HIDDEN_GROUP_WITH_ADMIN);
2320         }
2321     }
2322   else
2323     {
2324       if (AceSidCount == 0)
2325         {
2326           strcpy(GroupSecurityTemplate, NOT_HIDDEN_GROUP);
2327           sprintf(filter_exp, "(sAMAccountName=%s)", NOT_HIDDEN_GROUP);
2328         }
2329       else
2330         {
2331           strcpy(GroupSecurityTemplate, NOT_HIDDEN_GROUP_WITH_ADMIN);
2332           sprintf(filter_exp, "(sAMAccountName=%s)", NOT_HIDDEN_GROUP_WITH_ADMIN);
2333         }
2334     }
2335
2336   sprintf(search_path, "%s,%s", security_template_ou, dn_path);
2337   attr_array[0] = "sAMAccountName";
2338   attr_array[1] = NULL;
2339   group_count = 0;
2340   group_base = NULL;
2341   if ((rc = linklist_build(ldap_handle, search_path, filter_exp, attr_array, 
2342                                &group_base, &group_count, LDAP_SCOPE_SUBTREE) != 0))
2343     return(1);
2344   if (group_count != 1)
2345     {
2346       linklist_free(group_base);
2347       com_err(whoami, 0, "Unable to process group security template: %s - security not set", GroupSecurityTemplate);
2348       return(1);
2349     }
2350   strcpy(TemplateDn, group_base->dn);
2351   strcpy(TemplateSamName, group_base->value);
2352   linklist_free(group_base);
2353   group_base = NULL;
2354   group_count = 0;
2355
2356   sprintf(filter_exp, "(sAMAccountName=%s)", TemplateSamName);
2357   rc = ldap_search_ext_s(ldap_handle,
2358                          TemplateDn,
2359                          LDAP_SCOPE_SUBTREE,
2360                          filter_exp,
2361                          NULL,
2362                          0,
2363                          apsServerControls,
2364                          NULL,
2365                          NULL,
2366                          0,
2367                          &psMsg);
2368
2369   if ((psMsg = ldap_first_entry(ldap_handle, psMsg)) == NULL)
2370     {
2371       com_err(whoami, 0, "Unable to find group security template: %s - security not set", GroupSecurityTemplate);
2372       return(1);
2373     }
2374   ppsValues = ldap_get_values_len(ldap_handle, psMsg, "ntSecurityDescriptor");
2375   if (ppsValues == NULL)
2376     {
2377       com_err(whoami, 0, "Unable to find group security descriptor for group %s - security not set", GroupSecurityTemplate);
2378       return(1);
2379     }
2380
2381   if (AceSidCount != 0)
2382     {
2383       for (nVal = 0; ppsValues[nVal] != NULL; nVal++)
2384         {
2385           for (i = 0; i < (int)(ppsValues[nVal]->bv_len - UserTemplateSidCount); i++)
2386             {
2387               if (!memcmp(&ppsValues[nVal]->bv_val[i], UserTemplateSid, UserTemplateSidCount))
2388                 {
2389                   memcpy(&ppsValues[nVal]->bv_val[i], AceSid, AceSidCount);
2390                   break;
2391                 }
2392             }
2393         }
2394     }
2395
2396   n = 0;
2397   ADD_ATTR("ntSecurityDescriptor", (char **)ppsValues, LDAP_MOD_REPLACE | LDAP_MOD_BVALUES);
2398   mods[n] = NULL;
2399
2400   rc = ldap_modify_s(ldap_handle, TargetDn, mods);
2401   for (i = 0; i < n; i++)
2402     free(mods[i]);
2403   ldap_value_free_len(ppsValues);
2404   ldap_msgfree(psMsg);
2405   if (rc != LDAP_SUCCESS)
2406     {
2407       com_err(whoami, 0, "Unable to set security settings for group %s : %s",
2408               TargetGroupName, ldap_err2string(rc));
2409       if (AceSidCount != 0)
2410         {
2411           com_err(whoami, 0, "Trying to set security for group %s without admin.",
2412                   TargetGroupName);
2413           if (rc = ProcessGroupSecurity(ldap_handle, dn_path, TargetGroupName, 
2414                                         HiddenGroup, "", ""))
2415             {
2416               com_err(whoami, 0, "Unable to set security for group %s.",
2417                       TargetGroupName);
2418               return(rc);
2419             }
2420         }
2421       return(rc);
2422     }
2423   return(rc);
2424 }
2425
2426 int group_delete(LDAP *ldap_handle, char *dn_path, char *group_name, 
2427                  char *group_membership, char *MoiraId)
2428 {
2429   LK_ENTRY  *group_base;
2430   char      temp[512];
2431   char      filter[128];
2432   int       group_count;
2433   int       rc;
2434
2435   if (!check_string(group_name))
2436     {
2437       com_err(whoami, 0, "Unable to process invalid LDAP list name %s", group_name);
2438       return(AD_INVALID_NAME);
2439     }
2440
2441   memset(filter, '\0', sizeof(filter));
2442   group_count = 0;
2443   group_base = NULL;
2444   sprintf(temp, "%s,%s", group_ou_root, dn_path);
2445   if (rc = ad_get_group(ldap_handle, temp, group_name, 
2446                         group_membership, MoiraId, 
2447                         "distinguishedName", &group_base, 
2448                         &group_count, filter))
2449     return(rc);
2450
2451   if (group_count == 1)
2452     {
2453       if ((rc = ldap_delete_s(ldap_handle, group_base->value)) != LDAP_SUCCESS)
2454         {
2455           linklist_free(group_base);
2456           com_err(whoami, 0, "Unable to delete list %s from AD : %s",
2457                   group_name, ldap_err2string(rc));
2458           return(rc);
2459         }
2460       linklist_free(group_base);
2461     }
2462   else
2463     {
2464       linklist_free(group_base);
2465       com_err(whoami, 0, "Unable to find list %s in AD.", group_name);
2466       return(AD_NO_GROUPS_FOUND);
2467     }
2468
2469   return(0);
2470 }
2471
2472 int BEREncodeSecurityBits(ULONG uBits, char *pBuffer)
2473 {
2474     *pBuffer++ = 0x30;
2475     *pBuffer++ = 0x03;
2476     *pBuffer++ = 0x02;
2477     *pBuffer++ = 0x00;
2478     return(N_SD_BER_BYTES);
2479 }
2480
2481 int process_lists(int ac, char **av, void *ptr)
2482 {
2483   int   rc;
2484   int   security_flag;
2485   char  group_ou[256];
2486   char  group_membership[2];
2487   char  **call_args;
2488
2489   call_args = ptr;
2490
2491   security_flag = 0;
2492   memset(group_ou, '\0', sizeof(group_ou));
2493   memset(group_membership, '\0', sizeof(group_membership));
2494   get_group_membership(group_membership, group_ou, &security_flag, av);
2495   rc = member_add((LDAP *)call_args[0], (char *)call_args[1], av[L_NAME],
2496                   group_ou, group_membership, call_args[2], 
2497                   (char *)call_args[3], "");
2498   return(0);
2499 }
2500
2501 int member_list_build(int ac, char **av, void *ptr)
2502 {
2503   LK_ENTRY  *linklist;
2504   char      temp[1024];
2505   char      **call_args;
2506
2507   call_args = ptr;
2508
2509   strcpy(temp, av[ACE_NAME]);
2510   if (!check_string(temp))
2511     return(0);
2512   if (!strcmp(av[ACE_TYPE], "USER"))
2513     {
2514       if (!((int)call_args[3] & MOIRA_USERS))
2515         return(0);
2516     }
2517   else if (!strcmp(av[ACE_TYPE], "STRING"))
2518     {
2519       if (!((int)call_args[3] & MOIRA_STRINGS))
2520         return(0);
2521       if (contact_create((LDAP *)call_args[0], call_args[1], temp, contact_ou))
2522         return(0);
2523     }
2524   else if (!strcmp(av[ACE_TYPE], "LIST"))
2525     {
2526       if (!((int)call_args[3] & MOIRA_LISTS))
2527         return(0);
2528     }
2529   else if (!strcmp(av[ACE_TYPE], "KERBEROS"))
2530     {
2531       if (!((int)call_args[3] & MOIRA_KERBEROS))
2532         return(0);
2533       if (contact_create((LDAP *)call_args[0], call_args[1], temp, kerberos_ou))
2534         return(0);
2535     }
2536   else
2537     return(0);
2538
2539   linklist = member_base;
2540   while (linklist)
2541     {
2542     if (!strcasecmp(temp, linklist->member))
2543       return(0);
2544     linklist = linklist->next;
2545     }
2546   linklist = calloc(1, sizeof(LK_ENTRY));
2547   linklist->op = 1;
2548   linklist->dn = NULL;
2549   linklist->list = calloc(1, strlen(call_args[2]) + 1);
2550   strcpy(linklist->list, call_args[2]);
2551   linklist->type = calloc(1, strlen(av[ACE_TYPE]) + 1);
2552   strcpy(linklist->type, av[ACE_TYPE]);
2553   linklist->member = calloc(1, strlen(temp) + 1);
2554   strcpy(linklist->member, temp);
2555   linklist->next = member_base;
2556   member_base = linklist;
2557   return(0);
2558 }
2559
2560 int member_remove(LDAP *ldap_handle, char *dn_path, char *group_name, 
2561                   char *group_ou, char *group_membership, char *user_name,
2562                   char *UserOu, char *MoiraId)
2563 {
2564   char        distinguished_name[1024];
2565   char        *modvalues[2];
2566   char        temp[256];
2567   char        filter[128];
2568   int         group_count;
2569   int         i;
2570   int         n;
2571   LDAPMod     *mods[20];
2572   LK_ENTRY    *group_base;
2573   ULONG       rc;
2574
2575   if (!check_string(group_name))
2576     return(AD_INVALID_NAME);
2577
2578   memset(filter, '\0', sizeof(filter));
2579   group_base = NULL;
2580   group_count = 0;
2581   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
2582                         group_membership, MoiraId, 
2583                         "distinguishedName", &group_base, 
2584                         &group_count, filter))
2585     return(rc);
2586
2587   if (group_count != 1)
2588     {
2589       com_err(whoami, 0, "Unable to find list %s in AD",
2590               group_name);
2591       linklist_free(group_base);
2592       group_base = NULL;
2593       group_count = 0;
2594       goto cleanup;
2595     }
2596   strcpy(distinguished_name, group_base->value);
2597   linklist_free(group_base);
2598   group_base = NULL;
2599   group_count = 0;
2600
2601   sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
2602   modvalues[0] = temp;
2603   modvalues[1] = NULL;
2604
2605   n = 0;
2606   ADD_ATTR("member", modvalues, LDAP_MOD_DELETE);
2607   mods[n] = NULL;
2608   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
2609   for (i = 0; i < n; i++)
2610     free(mods[i]);
2611   if (rc == LDAP_UNWILLING_TO_PERFORM)
2612     rc = LDAP_SUCCESS;
2613   if (rc != LDAP_SUCCESS)
2614     {
2615       com_err(whoami, 0, "Unable to modify list %s members : %s",
2616               group_name, ldap_err2string(rc));
2617       goto cleanup;
2618     }
2619
2620 cleanup:
2621   return(rc);
2622 }
2623
2624 int member_add(LDAP *ldap_handle, char *dn_path, char *group_name, 
2625                char *group_ou, char *group_membership, char *user_name, 
2626                char *UserOu, char *MoiraId)
2627 {
2628   char        distinguished_name[1024];
2629   char        *modvalues[2];
2630   char        temp[256];
2631   char        filter[128];
2632   int         group_count;
2633   int         n;
2634   int         i;
2635   LDAPMod     *mods[20];
2636   LK_ENTRY    *group_base;
2637   ULONG       rc;
2638
2639   if (!check_string(group_name))
2640     return(AD_INVALID_NAME);
2641
2642   rc = 0;
2643   memset(filter, '\0', sizeof(filter));
2644   group_base = NULL;
2645   group_count = 0;
2646   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
2647                         group_membership, MoiraId, 
2648                         "distinguishedName", &group_base, 
2649                         &group_count, filter))
2650     return(rc);
2651
2652   if (group_count != 1)
2653     {
2654       linklist_free(group_base);
2655       group_base = NULL;
2656       group_count = 0;
2657       com_err(whoami, 0, "Unable to find list %s in AD",
2658               group_name);
2659       return(AD_MULTIPLE_GROUPS_FOUND);
2660     }
2661
2662   strcpy(distinguished_name, group_base->value);
2663   linklist_free(group_base);
2664   group_base = NULL;
2665   group_count = 0;
2666
2667   sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
2668   modvalues[0] = temp;
2669   modvalues[1] = NULL;
2670
2671   n = 0;
2672   ADD_ATTR("member", modvalues, LDAP_MOD_ADD);
2673   mods[n] = NULL;
2674   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
2675   if (rc == LDAP_ALREADY_EXISTS)
2676     rc = LDAP_SUCCESS;
2677   if ((!strcmp(UserOu, contact_ou)) || (!strcmp(UserOu, kerberos_ou)))
2678     {
2679       if (rc == LDAP_UNWILLING_TO_PERFORM)
2680         rc = LDAP_SUCCESS;
2681     }
2682   for (i = 0; i < n; i++)
2683     free(mods[i]);
2684   if (rc != LDAP_SUCCESS)
2685     {
2686       com_err(whoami, 0, "Unable to add %s to list %s as a member : %s",
2687               user_name, group_name, ldap_err2string(rc));
2688     }
2689
2690   return(rc);
2691 }
2692
2693 int contact_create(LDAP *ld, char *bind_path, char *user, char *group_ou)
2694 {
2695   LDAPMod *mods[20];
2696   char new_dn[256];
2697   char cn_user_name[256];
2698   char contact_name[256];
2699   char *email_v[] = {NULL, NULL};
2700   char *cn_v[] = {NULL, NULL};
2701   char *contact_v[] = {NULL, NULL};
2702   char *objectClass_v[] = {"top", "person", 
2703                            "organizationalPerson", 
2704                            "contact", NULL};
2705   char *name_v[] = {NULL, NULL};
2706   char *desc_v[] = {NULL, NULL};
2707   int  n;
2708   int  rc;
2709   int  i;
2710
2711   if (!check_string(user))
2712     {
2713       com_err(whoami, 0, "Unable to process invalid LDAP name %s", user);
2714       return(AD_INVALID_NAME);
2715     }
2716   strcpy(contact_name, user);
2717   sprintf(cn_user_name,"CN=%s,%s,%s", contact_name, group_ou, bind_path);
2718   cn_v[0] = cn_user_name;
2719   contact_v[0] = contact_name;
2720   name_v[0] = user;
2721   desc_v[0] = "Auto account created by Moira";
2722   email_v[0] = user;
2723
2724   strcpy(new_dn, cn_user_name);
2725   n = 0;
2726   ADD_ATTR("cn", contact_v, LDAP_MOD_ADD);
2727   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2728   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2729   ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2730   ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2731   if (!strcmp(group_ou, contact_ou))
2732     {
2733       ADD_ATTR("mail", email_v, LDAP_MOD_ADD);
2734     }
2735   mods[n] = NULL;
2736
2737   rc = ldap_add_ext_s(ld, new_dn, mods, NULL, NULL);
2738   for (i = 0; i < n; i++)
2739     free(mods[i]);
2740   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2741     {
2742       n = 0;
2743       ADD_ATTR("cn", contact_v, LDAP_MOD_ADD);
2744       ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2745       ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2746       ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2747       ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2748       mods[n] = NULL;
2749       rc = ldap_add_ext_s(ld, new_dn, mods, NULL, NULL);
2750       for (i = 0; i < n; i++)
2751         free(mods[i]);
2752     }
2753   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2754     {
2755       com_err(whoami, 0, "Unable to create contact %s : %s",
2756               user, ldap_err2string(rc));
2757       return(rc);
2758     }
2759   return(0);
2760 }
2761
2762 int user_update(LDAP *ldap_handle, char *dn_path, char *user_name,
2763                 char *Uid, char *MitId, char *MoiraId, int State,
2764                 char *WinHomeDir, char *WinProfileDir)
2765 {
2766   LDAPMod   *mods[20];
2767   LK_ENTRY  *group_base;
2768   int  group_count;
2769   char distinguished_name[512];
2770   char *mitMoiraId_v[] = {NULL, NULL};
2771   char *uid_v[] = {NULL, NULL};
2772   char *mitid_v[] = {NULL, NULL};
2773   char *homedir_v[] = {NULL, NULL};
2774   char *winProfile_v[] = {NULL, NULL};
2775   char *drives_v[] = {NULL, NULL};
2776   char *userAccountControl_v[] = {NULL, NULL};
2777   char userAccountControlStr[80];
2778   int  n;
2779   int  rc;
2780   int  i;
2781   int  OldUseSFU30;
2782   u_int userAccountControl = UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD | UF_PASSWD_CANT_CHANGE;
2783   char filter[128];
2784   char *attr_array[3];
2785   char temp[256];
2786
2787   if (!check_string(user_name))
2788     {
2789       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", user_name);
2790       return(AD_INVALID_NAME);
2791     }
2792
2793   group_count = 0;
2794   group_base = NULL;
2795
2796   if (strlen(MoiraId) != 0)
2797     {
2798       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
2799       attr_array[0] = "cn";
2800       attr_array[1] = NULL;
2801       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
2802                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
2803         {
2804           com_err(whoami, 0, "Unable to process user %s : %s",
2805                   user_name, ldap_err2string(rc));
2806           return(rc);
2807         }
2808     }
2809   if (group_count != 1)
2810     {
2811       linklist_free(group_base);
2812       group_base = NULL;
2813       group_count = 0;
2814       sprintf(filter, "(sAMAccountName=%s)", user_name);
2815       attr_array[0] = "cn";
2816       attr_array[1] = NULL;
2817       sprintf(temp, "%s,%s", user_ou, dn_path);
2818       if ((rc = linklist_build(ldap_handle, temp, filter, attr_array, 
2819                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
2820         {
2821           com_err(whoami, 0, "Unable to process user %s : %s",
2822                   user_name, ldap_err2string(rc));
2823           return(rc);
2824         }
2825     }
2826
2827   if (group_count != 1)
2828     {
2829       com_err(whoami, 0, "Unable to find user %s in AD",
2830               user_name);
2831       linklist_free(group_base);
2832       return(AD_NO_USER_FOUND);
2833     }
2834   strcpy(distinguished_name, group_base->dn);
2835
2836   linklist_free(group_base);
2837   group_count = 0;
2838
2839   if ((strlen(MitId) != 0) && (MitId[0] == '9'))
2840     rc = attribute_update(ldap_handle, distinguished_name, MitId, "employeeID", user_name);
2841   else
2842     rc = attribute_update(ldap_handle, distinguished_name, "none", "employeeID", user_name);
2843   rc = attribute_update(ldap_handle, distinguished_name, Uid, "uid", user_name);
2844   rc = attribute_update(ldap_handle, distinguished_name, MoiraId, "mitMoiraId", user_name);
2845
2846   n = 0;
2847   uid_v[0] = Uid;
2848   if (!UseSFU30)
2849     {
2850       ADD_ATTR("uidNumber", uid_v, LDAP_MOD_REPLACE);
2851     }
2852   else
2853     {
2854       ADD_ATTR("msSFU30UidNumber", uid_v, LDAP_MOD_REPLACE);
2855     }
2856
2857
2858   if ((State != US_NO_PASSWD) && (State != US_REGISTERED))
2859     userAccountControl |= UF_ACCOUNTDISABLE;
2860   sprintf(userAccountControlStr, "%ld", userAccountControl);
2861   userAccountControl_v[0] = userAccountControlStr;
2862   ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_REPLACE);
2863
2864   n = SetHomeDirectory(ldap_handle, user_name, distinguished_name, WinHomeDir, 
2865                        WinProfileDir, homedir_v, winProfile_v,
2866                        drives_v, mods, LDAP_MOD_REPLACE, n);
2867
2868   mods[n] = NULL;
2869   if ((rc = ldap_modify_s(ldap_handle, distinguished_name, mods)) != LDAP_SUCCESS)
2870     {
2871         OldUseSFU30 = UseSFU30;
2872         SwitchSFU(mods, &UseSFU30, n);
2873         if (OldUseSFU30 != UseSFU30)
2874             rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
2875         if (rc)
2876         {
2877             com_err(whoami, 0, "Unable to modify user data for %s : %s",
2878                 user_name, ldap_err2string(rc));
2879         }
2880     }
2881   for (i = 0; i < n; i++)
2882     free(mods[i]);
2883   return(rc);
2884 }
2885
2886 int user_rename(LDAP *ldap_handle, char *dn_path, char *before_user_name, 
2887                 char *user_name)
2888 {
2889   LDAPMod *mods[20];
2890   char new_dn[256];
2891   char old_dn[256];
2892   char upn[256];
2893   char temp[128];
2894   char *userPrincipalName_v[] = {NULL, NULL};
2895   char *altSecurityIdentities_v[] = {NULL, NULL};
2896   char *name_v[] = {NULL, NULL};
2897   char *samAccountName_v[] = {NULL, NULL};
2898   int  n;
2899   int  rc;
2900   int  i;
2901
2902   if (!check_string(before_user_name))
2903     {
2904       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", before_user_name);
2905       return(AD_INVALID_NAME);
2906     }
2907   if (!check_string(user_name))
2908     {
2909       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", user_name);
2910       return(AD_INVALID_NAME);
2911     }
2912
2913   strcpy(user_name, user_name);
2914   sprintf(old_dn, "cn=%s,%s,%s", before_user_name, user_ou, dn_path);
2915   sprintf(new_dn, "cn=%s", user_name);
2916   if ((rc = ldap_rename_s(ldap_handle, old_dn, new_dn, NULL, TRUE, 
2917                            NULL, NULL)) != LDAP_SUCCESS)
2918     {
2919       com_err(whoami, 0, "Unable to rename user from %s to %s : %s",
2920               before_user_name, user_name, ldap_err2string(rc));
2921       return(rc);
2922     }
2923
2924   name_v[0] = user_name;
2925   sprintf(upn, "%s@%s", user_name, ldap_domain);
2926   userPrincipalName_v[0] = upn;
2927   sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
2928   altSecurityIdentities_v[0] = temp;
2929   samAccountName_v[0] = user_name;
2930
2931   n = 0;
2932   ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_REPLACE);
2933   ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_REPLACE);
2934   ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
2935   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_REPLACE);
2936   mods[n] = NULL;
2937   sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, dn_path);
2938   if ((rc = ldap_modify_s(ldap_handle, new_dn, mods)) != LDAP_SUCCESS)
2939     {
2940       com_err(whoami, 0, "Unable to modify user data for %s after renaming : %s",
2941               user_name, ldap_err2string(rc));
2942     }
2943   for (i = 0; i < n; i++)
2944     free(mods[i]);
2945   return(rc);
2946 }
2947
2948
2949 int user_create(int ac, char **av, void *ptr)
2950 {
2951   LDAPMod *mods[20];
2952   char new_dn[256];
2953   char user_name[256];
2954   char sam_name[256];
2955   char upn[256];
2956   char *cn_v[] = {NULL, NULL};
2957   char *objectClass_v[] = {"top", "person", 
2958                            "organizationalPerson", 
2959                            "user", NULL};
2960
2961   char *samAccountName_v[] = {NULL, NULL};
2962   char *altSecurityIdentities_v[] = {NULL, NULL};
2963   char *mitMoiraId_v[] = {NULL, NULL};
2964   char *name_v[] = {NULL, NULL};
2965   char *desc_v[] = {NULL, NULL};
2966   char *userPrincipalName_v[] = {NULL, NULL};
2967   char *userAccountControl_v[] = {NULL, NULL};
2968   char *uid_v[] = {NULL, NULL};
2969   char *mitid_v[] = {NULL, NULL};
2970   char *homedir_v[] = {NULL, NULL};
2971   char *winProfile_v[] = {NULL, NULL};
2972   char *drives_v[] = {NULL, NULL};
2973   char userAccountControlStr[80];
2974   char temp[128];
2975   u_int userAccountControl = UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD | UF_PASSWD_CANT_CHANGE;
2976   int  n;
2977   int  rc;
2978   int  i;
2979   int  OldUseSFU30;
2980   char **call_args;
2981   char WinHomeDir[1024];
2982   char WinProfileDir[1024];
2983
2984   call_args = ptr;
2985
2986   if (!check_string(av[U_NAME]))
2987     {
2988       callback_rc = AD_INVALID_NAME;
2989       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", av[U_NAME]);
2990       return(AD_INVALID_NAME);
2991     }
2992
2993   memset(WinHomeDir, '\0', sizeof(WinHomeDir));
2994   memset(WinProfileDir, '\0', sizeof(WinProfileDir));
2995   strcpy(WinHomeDir, av[U_WINHOMEDIR]);
2996   strcpy(WinProfileDir, av[U_WINPROFILEDIR]);
2997   strcpy(user_name, av[U_NAME]);
2998   sprintf(upn, "%s@%s", user_name, ldap_domain);
2999   sprintf(sam_name, "%s", av[U_NAME]);
3000   samAccountName_v[0] = sam_name;
3001   if ((atoi(av[U_STATE]) != US_NO_PASSWD) && (atoi(av[U_STATE]) != US_REGISTERED))
3002     userAccountControl |= UF_ACCOUNTDISABLE;
3003   sprintf(userAccountControlStr, "%ld", userAccountControl);
3004   userAccountControl_v[0] = userAccountControlStr;
3005   userPrincipalName_v[0] = upn;
3006
3007   cn_v[0] = user_name;
3008   name_v[0] = user_name;
3009   desc_v[0] = "Auto account created by Moira";
3010   sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
3011   altSecurityIdentities_v[0] = temp;    
3012   sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, call_args[1]);
3013
3014   n = 0;
3015   ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
3016   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
3017   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
3018   ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_ADD);
3019   ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_ADD);
3020   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
3021   ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
3022   ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
3023   if (strlen(call_args[2]) != 0)    
3024     {
3025       mitMoiraId_v[0] = call_args[2];
3026       ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_ADD);
3027     }
3028   ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_ADD);
3029   if (strlen(av[U_UID]) != 0)
3030     {
3031       uid_v[0] = av[U_UID];
3032       ADD_ATTR("uid", uid_v, LDAP_MOD_ADD);
3033       if (!UseSFU30)
3034         {
3035           ADD_ATTR("uidNumber", uid_v, LDAP_MOD_ADD);
3036         }
3037       else
3038         {
3039           ADD_ATTR("msSFU30UidNumber", uid_v, LDAP_MOD_ADD);
3040         }
3041     }
3042   if ((strlen(av[U_MITID]) != 0) && (av[U_MITID][0] == '9'))
3043       mitid_v[0] = av[U_MITID];
3044   else
3045       mitid_v[0] = "none";
3046   ADD_ATTR("employeeID", mitid_v, LDAP_MOD_ADD);
3047
3048   n = SetHomeDirectory((LDAP *)call_args[0], user_name, new_dn, WinHomeDir, 
3049                        WinProfileDir, homedir_v, winProfile_v,
3050                        drives_v, mods, LDAP_MOD_ADD, n);
3051
3052   mods[n] = NULL;
3053
3054   rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
3055   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
3056   {
3057       OldUseSFU30 = UseSFU30;
3058       SwitchSFU(mods, &UseSFU30, n);
3059       if (OldUseSFU30 != UseSFU30)
3060           rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
3061   }
3062
3063   for (i = 0; i < n; i++)
3064     free(mods[i]);
3065   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
3066     {
3067       com_err(whoami, 0, "Unable to create user %s : %s",
3068               user_name, ldap_err2string(rc));
3069       callback_rc = rc;
3070       return(rc);
3071     }
3072   if (rc == LDAP_SUCCESS)
3073     {
3074       if ((rc = set_password(sam_name, "", ldap_domain)) != 0)
3075         {
3076           ad_kdc_disconnect();
3077           tickets_get_k5();
3078           if (!ad_server_connect(default_server, ldap_domain))
3079             {
3080               com_err(whoami, 0, "Unable to set password for user %s : %s",
3081                       user_name, "cannot get changepw ticket from windows domain");
3082             }
3083           else
3084             {
3085               if ((rc = set_password(sam_name, "", ldap_domain)) != 0)
3086                 {
3087                   com_err(whoami, 0, "Unable to set password for user %s : %ld",
3088                           user_name, rc);
3089                 }
3090             }
3091         }
3092     }
3093   return(0);
3094 }
3095
3096 int user_change_status(LDAP *ldap_handle, char *dn_path, 
3097                        char *user_name, char *MoiraId,
3098                        int operation)
3099 {
3100   char      filter[128];
3101   char      *attr_array[3];
3102   char      temp[256];
3103   char      distinguished_name[1024];
3104   char      **modvalues;
3105   char      *mitMoiraId_v[] = {NULL, NULL};
3106   LDAPMod   *mods[20];
3107   LK_ENTRY  *group_base;
3108   int       group_count;
3109   int       rc;
3110   int       i;
3111   int       n;
3112   ULONG     ulongValue;
3113
3114   if (!check_string(user_name))
3115     {
3116       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", user_name);
3117       return(AD_INVALID_NAME);
3118     }
3119
3120   group_count = 0;
3121   group_base = NULL;
3122
3123   if (strlen(MoiraId) != 0)
3124     {
3125       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
3126       attr_array[0] = "UserAccountControl";
3127       attr_array[1] = NULL;
3128       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3129                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3130         {
3131           com_err(whoami, 0, "Unable to process user %s : %s",
3132                   user_name, ldap_err2string(rc));
3133           return(rc);
3134         }
3135     }
3136   if (group_count != 1)
3137     {
3138       linklist_free(group_base);
3139       group_count = 0;
3140       group_base = NULL;
3141       sprintf(filter, "(sAMAccountName=%s)", user_name);
3142       attr_array[0] = "UserAccountControl";
3143       attr_array[1] = NULL;
3144       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3145                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3146         {
3147           com_err(whoami, 0, "Unable to process user %s : %s",
3148                   user_name, ldap_err2string(rc));
3149           return(rc);
3150         }
3151     }
3152
3153   if (group_count != 1)
3154     {
3155       linklist_free(group_base);
3156       com_err(whoami, 0, "Unable to find user %s in AD",
3157               user_name);
3158       return(LDAP_NO_SUCH_OBJECT);
3159     }
3160
3161   strcpy(distinguished_name, group_base->dn);
3162   ulongValue = atoi((*group_base).value);
3163   if (operation == MEMBER_DEACTIVATE)
3164     ulongValue |= UF_ACCOUNTDISABLE;
3165   else    
3166     ulongValue &= ~UF_ACCOUNTDISABLE;
3167   sprintf(temp, "%ld", ulongValue);
3168   if ((rc = construct_newvalues(group_base, group_count, (*group_base).value, 
3169                                 temp, &modvalues, REPLACE)) == 1)
3170     goto cleanup;
3171   linklist_free(group_base);
3172   group_base = NULL;
3173   group_count = 0;
3174   n = 0;
3175   ADD_ATTR("UserAccountControl", modvalues, LDAP_MOD_REPLACE);
3176   if (strlen(MoiraId) != 0)
3177     {
3178     mitMoiraId_v[0] = MoiraId;
3179     ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
3180     }
3181   mods[n] = NULL;
3182   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
3183   for (i = 0; i < n; i++)
3184     free(mods[i]);
3185   free_values(modvalues);
3186   if (rc != LDAP_SUCCESS)
3187     {
3188       com_err(whoami, 0, "Unable to change status of user %s : %s",
3189               user_name, ldap_err2string(rc));
3190     }
3191 cleanup:
3192   return(rc);
3193 }
3194
3195 int user_delete(LDAP *ldap_handle, char *dn_path, 
3196                 char *u_name, char *MoiraId)
3197 {
3198   char      filter[128];
3199   char      *attr_array[3];
3200   char      distinguished_name[1024];
3201   char      user_name[512];
3202   LK_ENTRY  *group_base;
3203   int       group_count;
3204   int       rc;
3205
3206   if (!check_string(u_name))
3207     return(AD_INVALID_NAME);
3208
3209   strcpy(user_name, u_name);
3210   group_count = 0;
3211   group_base = NULL;
3212
3213   if (strlen(MoiraId) != 0)
3214     {
3215       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
3216       attr_array[0] = "name";
3217       attr_array[1] = NULL;
3218       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3219                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3220         {
3221           com_err(whoami, 0, "Unable to process user %s : %s",
3222                   user_name, ldap_err2string(rc));
3223           goto cleanup;
3224         }
3225     }
3226   if (group_count != 1)
3227     {
3228       linklist_free(group_base);
3229       group_count = 0;
3230       group_base = NULL;
3231       sprintf(filter, "(sAMAccountName=%s)", user_name);
3232       attr_array[0] = "name";
3233       attr_array[1] = NULL;
3234       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3235                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3236         {
3237           com_err(whoami, 0, "Unable to process user %s : %s",
3238                   user_name, ldap_err2string(rc));
3239           goto cleanup;
3240         }
3241     }
3242
3243   if (group_count != 1)
3244     {
3245       com_err(whoami, 0, "Unable to find user %s in AD",
3246               user_name);
3247       goto cleanup;
3248     }
3249
3250   strcpy(distinguished_name, group_base->dn);
3251   if (rc = ldap_delete_s(ldap_handle, distinguished_name))
3252     {
3253       com_err(whoami, 0, "Unable to process user %s : %s",
3254               user_name, ldap_err2string(rc));
3255     }
3256
3257 cleanup:
3258   linklist_free(group_base);
3259   return(0);
3260 }
3261
3262 void linklist_free(LK_ENTRY *linklist_base)
3263 {
3264   LK_ENTRY *linklist_previous;
3265
3266   while (linklist_base != NULL)
3267     {
3268       if (linklist_base->dn != NULL)
3269         free(linklist_base->dn);
3270       if (linklist_base->attribute != NULL)
3271         free(linklist_base->attribute);
3272       if (linklist_base->value != NULL)
3273         free(linklist_base->value);
3274       if (linklist_base->member != NULL)
3275         free(linklist_base->member);
3276       if (linklist_base->type != NULL)
3277         free(linklist_base->type);
3278       if (linklist_base->list != NULL)
3279         free(linklist_base->list);
3280       linklist_previous = linklist_base;
3281       linklist_base = linklist_previous->next;
3282       free(linklist_previous);
3283     }
3284 }
3285
3286 void free_values(char **modvalues)
3287 {
3288   int i;
3289
3290   i = 0;
3291   if (modvalues != NULL)
3292     {
3293     while (modvalues[i] != NULL)
3294       {
3295         free(modvalues[i]);
3296         modvalues[i] = NULL;
3297         ++i;
3298       }
3299     free(modvalues);
3300   }
3301 }
3302
3303 static int illegalchars[] = {
3304   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
3305   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
3306   1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, /* SPACE - / */
3307   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 0 - ? */
3308   0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
3309   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* P - _ */
3310   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
3311   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
3312   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
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 };
3321
3322 int check_string(char *s)
3323 {
3324   char  character;
3325
3326   for (; *s; s++)
3327     {
3328       character = *s;
3329       if (isupper(character))
3330         character = tolower(character);
3331       if (illegalchars[(unsigned) character])
3332         return 0;
3333     }
3334   return 1;
3335 }
3336
3337 int check_container_name(char *s)
3338 {
3339   char  character;
3340
3341   for (; *s; s++)
3342     {
3343       character = *s;
3344       if (isupper(character))
3345         character = tolower(character);
3346
3347           if (character == ' ')
3348                   continue;
3349       if (illegalchars[(unsigned) character])
3350         return 0;
3351     }
3352   return 1;
3353 }
3354
3355 int mr_connect_cl(char *server, char *client, int version, int auth)
3356 {
3357   int   status;
3358   char  *motd;
3359   char  temp[128];
3360
3361   status = mr_connect(server);
3362   if (status)
3363     {
3364       com_err(whoami, status, "while connecting to Moira");
3365       return status;
3366     }
3367
3368   status = mr_motd(&motd);
3369   if (status)
3370     {
3371       mr_disconnect();
3372       com_err(whoami, status, "while checking server status");
3373       return status;
3374     }
3375   if (motd)
3376     {
3377       sprintf(temp, "The Moira server is currently unavailable: %s", motd);
3378       com_err(whoami, status, temp);
3379       mr_disconnect();
3380       return status;
3381     }
3382
3383   status = mr_version(version);
3384   if (status)
3385     {
3386       if (status == MR_UNKNOWN_PROC)
3387         {
3388           if (version > 2)
3389             status = MR_VERSION_HIGH;
3390           else
3391             status = MR_SUCCESS;
3392         }
3393
3394       if (status == MR_VERSION_HIGH)
3395         {
3396           com_err(whoami, 0, "Warning: This client is running newer code than the server.");
3397                   com_err(whoami, 0, "Some operations may not work.");
3398         }
3399       else if (status && status != MR_VERSION_LOW)
3400         {
3401           com_err(whoami, status, "while setting query version number.");
3402           mr_disconnect();
3403           return status;
3404         }
3405     }
3406
3407   if (auth)
3408     {
3409       status = mr_krb5_auth(client);
3410       if (status)
3411         {
3412           com_err(whoami, status, "while authenticating to Moira.");
3413           mr_disconnect();
3414           return status;
3415         }
3416     }
3417
3418   return MR_SUCCESS;
3419 }
3420
3421 void AfsToWinAfs(char* path, char* winPath)
3422 {
3423     char* pathPtr;
3424     char* winPathPtr;
3425     strcpy(winPath, WINAFS);
3426     pathPtr = path + strlen(AFS);
3427     winPathPtr = winPath + strlen(WINAFS);
3428
3429     while (*pathPtr)
3430     {
3431         if (*pathPtr == '/')
3432           *winPathPtr = '\\';
3433         else
3434           *winPathPtr = *pathPtr;
3435
3436         pathPtr++;
3437         winPathPtr++;
3438     }
3439 }
3440
3441 int GetAceInfo(int ac, char **av, void *ptr)
3442 {
3443   char **call_args;
3444   int   security_flag;
3445
3446   call_args = ptr;
3447
3448   strcpy(call_args[0], av[L_ACE_TYPE]);
3449   strcpy(call_args[1], av[L_ACE_NAME]);
3450   security_flag = 0;
3451   get_group_membership(call_args[2], call_args[3], &security_flag, av);
3452   return(LDAP_SUCCESS);
3453
3454 }
3455
3456 int checkADname(LDAP *ldap_handle, char *dn_path, char *Name)
3457 {
3458   char filter[128];
3459   char *attr_array[3];
3460   int  group_count;
3461   int  rc;
3462   LK_ENTRY  *group_base;
3463
3464   group_count = 0;
3465   group_base = NULL;
3466
3467   sprintf(filter, "(sAMAccountName=%s)", Name);
3468   attr_array[0] = "sAMAccountName";
3469   attr_array[1] = NULL;
3470   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3471                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3472     {
3473       com_err(whoami, 0, "Unable to process ACE name %s : %s",
3474               Name, ldap_err2string(rc));
3475       return(1);
3476     }
3477
3478   linklist_free(group_base);
3479   group_base = NULL;
3480   if (group_count == 0)
3481     return(0);
3482   return(1);
3483 }
3484
3485 #define MAX_ACE 7
3486
3487 int ProcessAce(LDAP *ldap_handle, char *dn_path, char *Name, char *Type, int UpdateGroup, int *ProcessGroup)
3488 {
3489   char  *av[2];
3490   char  GroupName[256];
3491   char  *call_args[7];
3492   int   rc;
3493   char  *AceInfo[4];
3494   char  AceType[32];
3495   char  AceName[128];
3496   char  AceMembership[2];
3497   char  AceOu[256];
3498   char  temp[128];
3499
3500   strcpy(GroupName, Name);
3501
3502   if (strcasecmp(Type, "LIST"))
3503     return(1);
3504   while (1)
3505     {
3506       av[0] = GroupName;
3507       AceInfo[0] = AceType;
3508       AceInfo[1] = AceName;
3509       AceInfo[2] = AceMembership;
3510       AceInfo[3] = AceOu;
3511       memset(AceType, '\0', sizeof(AceType));
3512       memset(AceName, '\0', sizeof(AceName));
3513       memset(AceMembership, '\0', sizeof(AceMembership));
3514       memset(AceOu, '\0', sizeof(AceOu));
3515       callback_rc = 0;
3516       if (rc = mr_query("get_list_info", 1, av, GetAceInfo, AceInfo))
3517         {
3518           com_err(whoami, 0, "Unable to get ACE info for list %s : %s", GroupName, error_message(rc));
3519           return(1);
3520         }
3521       if (callback_rc)
3522         {
3523           com_err(whoami, 0, "Unable to get ACE info for list %s", GroupName);
3524           return(1);
3525         }
3526       if ((strcasecmp(AceType, "USER")) && (strcasecmp(AceType, "LIST")))
3527         return(0);
3528       strcpy(temp, AceName);
3529       if (!strcasecmp(AceType, "LIST"))
3530         sprintf(temp, "%s_group", AceName);
3531       if (!UpdateGroup)
3532         {
3533           if (checkADname(ldap_handle, dn_path, temp))
3534             return(0);
3535           (*ProcessGroup) = 1;
3536         }
3537       if (!strcasecmp(AceInfo[0], "LIST"))
3538         {
3539           if (make_new_group(ldap_handle, dn_path, "", AceName, AceOu, AceMembership, 0, UpdateGroup))
3540             return(1);
3541         }
3542       else if (!strcasecmp(AceInfo[0], "USER"))
3543         {
3544           av[0] = AceName;
3545           call_args[0] = (char *)ldap_handle;
3546           call_args[1] = dn_path;
3547           call_args[2] = "";
3548           call_args[3] = NULL;
3549           callback_rc = 0;
3550           if (rc = mr_query("get_user_account_by_login", 1, av, user_create, call_args))
3551             {
3552               com_err(whoami, 0, "Unable to process user ACE %s for group %s.", AceName, Name);
3553               return(1);
3554             }
3555           if (callback_rc)
3556             {
3557               com_err(whoami, 0, "Unable to process user Ace %s for group %s", AceName, Name);
3558               return(1);
3559             }
3560           return(0);
3561         }
3562       else
3563         return(1);
3564       if (!strcasecmp(AceType, "LIST"))
3565         {
3566           if (!strcasecmp(GroupName, AceName))
3567             return(0);
3568         }
3569       strcpy(GroupName, AceName);
3570     }
3571   return(1);
3572 }
3573
3574 int make_new_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
3575                    char *group_name, char *group_ou, char *group_membership, 
3576                    int group_security_flag, int updateGroup)
3577 {
3578   char  *av[3];
3579   char  *call_args[7];
3580   int   rc;
3581
3582   av[0] = group_name;
3583   call_args[0] = (char *)ldap_handle;
3584   call_args[1] = dn_path;
3585   call_args[2] = group_name;
3586   call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
3587   call_args[4] = (char *)updateGroup;
3588   call_args[5] = MoiraId;
3589   call_args[6] = NULL;
3590   callback_rc = 0;
3591   if (rc = mr_query("get_list_info", 1, av, group_create, call_args))
3592     {
3593       moira_disconnect();
3594       com_err(whoami, 0, "Unable to create list %s : %s", group_name, error_message(rc));
3595       return(rc);
3596     }
3597   if (callback_rc)
3598     {
3599       moira_disconnect();
3600       com_err(whoami, 0, "Unable to create list %s", group_name);
3601       return(callback_rc);
3602     }
3603
3604   return(0);
3605 }
3606
3607 int populate_group(LDAP *ldap_handle, char *dn_path, char *group_name, 
3608                    char *group_ou, char *group_membership, 
3609                    int group_security_flag, char *MoiraId)
3610 {
3611   char      *av[3];
3612   char      *call_args[7];
3613   char      *pUserOu;
3614   LK_ENTRY  *ptr;
3615   int       rc;
3616
3617   com_err(whoami, 0, "Populating group %s", group_name);
3618   av[0] = group_name;
3619   call_args[0] = (char *)ldap_handle;
3620   call_args[1] = dn_path;
3621   call_args[2] = group_name;
3622   call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
3623   call_args[4] = NULL;
3624   member_base = NULL;
3625   if (rc = mr_query("get_end_members_of_list", 1, av,
3626                     member_list_build, call_args))
3627     {
3628       com_err(whoami, 0, "Unable to populate list %s : %s", 
3629               group_name, error_message(rc));
3630       return(3);
3631     }
3632   if (member_base != NULL)
3633     {
3634       ptr = member_base;
3635       while (ptr != NULL)
3636         {
3637           if (!strcasecmp(ptr->type, "LIST"))
3638             {
3639               ptr = ptr->next;
3640               continue;
3641             }
3642           pUserOu = user_ou;
3643           if (!strcasecmp(ptr->type, "STRING"))
3644             {
3645               if (contact_create(ldap_handle, dn_path, ptr->member, contact_ou))
3646                 return(3);
3647               pUserOu = contact_ou;
3648             }
3649           else if (!strcasecmp(ptr->type, "KERBEROS"))
3650             {
3651               if (contact_create(ldap_handle, dn_path, ptr->member, kerberos_ou))
3652                 return(3);
3653               pUserOu = kerberos_ou;
3654             }
3655           rc = member_add(ldap_handle, dn_path, group_name,
3656                           group_ou, group_membership, ptr->member, 
3657                           pUserOu, MoiraId);
3658           ptr = ptr->next;
3659         }
3660       linklist_free(member_base);
3661       member_base = NULL;
3662     }
3663   return(0);
3664 }
3665
3666 int process_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
3667                   char *group_name, char *group_ou, char *group_membership, 
3668                   int group_security_flag, int type)
3669 {
3670   char      before_desc[512];
3671   char      before_name[256];
3672   char      before_group_ou[256];
3673   char      before_group_membership[2];
3674   char      distinguishedName[256];
3675   char      ad_distinguishedName[256];
3676   char      filter[128];
3677   char      *attr_array[3];
3678   int       before_security_flag;
3679   int       group_count;
3680   int       rc;
3681   LK_ENTRY  *group_base;
3682   LK_ENTRY  *ptr;
3683   char      ou_both[512];
3684   char      ou_security[512];
3685   char      ou_distribution[512];
3686   char      ou_neither[512];
3687
3688   memset(ad_distinguishedName, '\0', sizeof(ad_distinguishedName));
3689   sprintf(distinguishedName, "CN=%s,%s,%s", group_name, group_ou, dn_path);
3690
3691
3692   memset(filter, '\0', sizeof(filter));
3693   group_base = NULL;
3694   group_count = 0;
3695   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
3696                         "*", MoiraId, 
3697                         "distinguishedName", &group_base, 
3698                         &group_count, filter))
3699     return(rc);
3700
3701   if (type == CHECK_GROUPS)
3702     {
3703       if (group_count == 1)
3704         {
3705           if (!strcasecmp(group_base->value, distinguishedName))
3706             {
3707               linklist_free(group_base);
3708               return(0);
3709             }
3710         }
3711       linklist_free(group_base);
3712       if (group_count == 0)
3713         return(AD_NO_GROUPS_FOUND);
3714       if (group_count == 1)
3715         return(AD_WRONG_GROUP_DN_FOUND);
3716       return(AD_MULTIPLE_GROUPS_FOUND);
3717     }
3718   if (group_count == 0)
3719     {
3720       return(AD_NO_GROUPS_FOUND);
3721     }
3722   if (group_count > 1)
3723     {
3724       ptr = group_base;
3725       while (ptr != NULL)
3726         {
3727           if (!strcasecmp(distinguishedName, ptr->value))
3728             break;
3729           ptr = ptr->next;
3730         }
3731       if (ptr == NULL)
3732         {
3733           com_err(whoami, 0, "%d groups with moira id = %s", group_count, MoiraId);
3734           ptr = group_base;
3735           while (ptr != NULL)
3736             {
3737               com_err(whoami, 0, "%s with moira id = %s", ptr->value, MoiraId);
3738               ptr = ptr->next;
3739             }
3740           linklist_free(group_base);
3741           return(AD_MULTIPLE_GROUPS_FOUND);
3742         }
3743       ptr = group_base;
3744       while (ptr != NULL)
3745         {
3746           if (strcasecmp(distinguishedName, ptr->value))
3747             rc = ldap_delete_s(ldap_handle, ptr->value);
3748           ptr = ptr->next;
3749         }
3750       linklist_free(group_base);
3751       memset(filter, '\0', sizeof(filter));
3752       group_base = NULL;
3753       group_count = 0;
3754       if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
3755                             "*", MoiraId, 
3756                             "distinguishedName", &group_base, 
3757                             &group_count, filter))
3758         return(rc);
3759       if (group_count == 0)
3760         return(AD_NO_GROUPS_FOUND);
3761       if (group_count > 1)
3762         return(AD_MULTIPLE_GROUPS_FOUND);
3763     }
3764
3765   strcpy(ad_distinguishedName, group_base->value);
3766   linklist_free(group_base);
3767   group_base = NULL;
3768   group_count = 0;
3769
3770   attr_array[0] = "sAMAccountName";
3771   attr_array[1] = NULL;
3772   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3773                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3774     {
3775       com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
3776                MoiraId, ldap_err2string(rc));
3777       return(rc);
3778     }
3779   sprintf(filter, "(sAMAccountName=%s)", group_base->value);
3780
3781   if (!strcasecmp(ad_distinguishedName, distinguishedName))
3782     {
3783       linklist_free(group_base);
3784       group_base = NULL;
3785       group_count = 0;
3786       return(0);
3787     }
3788   linklist_free(group_base);
3789   group_base = NULL;
3790   group_count = 0;
3791   memset(ou_both, '\0', sizeof(ou_both));
3792   memset(ou_security, '\0', sizeof(ou_security));
3793   memset(ou_distribution, '\0', sizeof(ou_distribution));
3794   memset(ou_neither, '\0', sizeof(ou_neither));
3795   memset(before_name, '\0', sizeof(before_name));
3796   memset(before_desc, '\0', sizeof(before_desc));
3797   memset(before_group_membership, '\0', sizeof(before_group_membership));
3798   attr_array[0] = "name";
3799   attr_array[1] = NULL;
3800   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3801                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3802     {
3803       com_err(whoami, 0, "Unable to get list name with MoiraId = %s: %s",
3804               MoiraId, ldap_err2string(rc));
3805       return(rc);
3806     }
3807   strcpy(before_name, group_base->value);
3808   linklist_free(group_base);
3809   group_base = NULL;
3810   group_count = 0;
3811   attr_array[0] = "description";
3812   attr_array[1] = NULL;
3813   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3814                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3815     {
3816       com_err(whoami, 0, 
3817               "Unable to get list description with MoiraId = %s: %s",
3818               MoiraId, ldap_err2string(rc));
3819       return(rc);
3820     }
3821   if (group_count != 0)
3822     {
3823       strcpy(before_desc, group_base->value);
3824       linklist_free(group_base);
3825       group_base = NULL;
3826       group_count = 0;
3827     }
3828   change_to_lower_case(ad_distinguishedName);  
3829   strcpy(ou_both, group_ou_both);
3830   change_to_lower_case(ou_both);
3831   strcpy(ou_security, group_ou_security);
3832   change_to_lower_case(ou_security);
3833   strcpy(ou_distribution, group_ou_distribution);
3834   change_to_lower_case(ou_distribution);
3835   strcpy(ou_neither, group_ou_neither);
3836   change_to_lower_case(ou_neither);
3837   if (strstr(ad_distinguishedName, ou_both))
3838     {
3839       strcpy(before_group_ou, group_ou_both);
3840       before_group_membership[0] = 'B';
3841       before_security_flag = 1;
3842     }
3843   else if (strstr(ad_distinguishedName, ou_security))
3844     {
3845       strcpy(before_group_ou, group_ou_security);
3846       before_group_membership[0] = 'S';
3847       before_security_flag = 1;
3848     }
3849   else if (strstr(ad_distinguishedName, ou_distribution))
3850     {
3851       strcpy(before_group_ou, group_ou_distribution);
3852       before_group_membership[0] = 'D';
3853       before_security_flag = 0;
3854     }
3855   else if (strstr(ad_distinguishedName, ou_neither))
3856     {
3857       strcpy(before_group_ou, group_ou_neither);
3858       before_group_membership[0] = 'N';
3859       before_security_flag = 0;
3860     }
3861   else
3862     return(AD_NO_OU_FOUND);
3863   rc = group_rename(ldap_handle, dn_path, before_name, before_group_membership, 
3864                     before_group_ou, before_security_flag, before_desc,
3865                     group_name, group_membership, group_ou, group_security_flag,
3866                     before_desc, MoiraId, filter);
3867   return(rc);
3868 }
3869
3870 void change_to_lower_case(char *ptr)
3871 {
3872   int i;
3873
3874   for (i = 0; i < (int)strlen(ptr); i++)
3875     {
3876       ptr[i] = tolower(ptr[i]);
3877     }
3878 }
3879
3880 int ad_get_group(LDAP *ldap_handle, char *dn_path, 
3881                  char *group_name, char *group_membership, 
3882                  char *MoiraId, char *attribute,
3883                  LK_ENTRY **linklist_base, int *linklist_count,
3884                  char *rFilter)
3885 {
3886   LK_ENTRY  *pPtr;
3887   char  filter[128];
3888   char  *attr_array[3];
3889   int   rc;
3890
3891   (*linklist_base) = NULL;
3892   (*linklist_count) = 0;
3893   if (strlen(rFilter) != 0)
3894     {
3895       strcpy(filter, rFilter);
3896       attr_array[0] = attribute;
3897       attr_array[1] = NULL;
3898       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3899                                linklist_base, linklist_count, LDAP_SCOPE_SUBTREE)) != 0)
3900         {
3901           com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
3902                   MoiraId, ldap_err2string(rc));
3903          return(rc);
3904        }
3905     if ((*linklist_count) == 1)
3906       {
3907         strcpy(rFilter, filter);
3908         return(0);
3909       }
3910     }
3911
3912   linklist_free((*linklist_base));
3913   (*linklist_base) = NULL;
3914   (*linklist_count) = 0;
3915   if (strlen(MoiraId) != 0)
3916     {
3917       sprintf(filter, "(&(objectClass=group)(mitMoiraId=%s))", MoiraId);
3918       attr_array[0] = attribute;
3919       attr_array[1] = NULL;
3920       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3921                                linklist_base, linklist_count, LDAP_SCOPE_SUBTREE)) != 0)
3922         {
3923           com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
3924                   MoiraId, ldap_err2string(rc));
3925          return(rc);
3926        }
3927     }
3928   if ((*linklist_count) > 1)
3929     {
3930       com_err(whoami, 0, "multiple groups with mitMoiraId = %s", MoiraId);
3931       pPtr = (*linklist_base);
3932       while (pPtr)
3933         {
3934           com_err(whoami, 0, "groups %s has mitMoiraId = %s", pPtr->value, MoiraId);
3935           pPtr = pPtr->next;
3936         }
3937       linklist_free((*linklist_base));
3938       (*linklist_base) = NULL;
3939       (*linklist_count) = 0;
3940     }
3941   if ((*linklist_count) == 1)
3942     {
3943       if (!memcmp(&(*linklist_base)->value[3], group_name, strlen(group_name)))
3944         {
3945           strcpy(rFilter, filter);
3946           return(0);
3947         }
3948     }
3949
3950   linklist_free((*linklist_base));
3951   (*linklist_base) = NULL;
3952   (*linklist_count) = 0;
3953   sprintf(filter, "(sAMAccountName=%s_group)", group_name);
3954   attr_array[0] = attribute;
3955   attr_array[1] = NULL;
3956   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3957                            linklist_base, linklist_count, LDAP_SCOPE_SUBTREE)) != 0)
3958     {
3959       com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
3960               MoiraId, ldap_err2string(rc));
3961       return(rc);
3962     }
3963   if ((*linklist_count) == 1)
3964     {
3965       strcpy(rFilter, filter);
3966       return(0);
3967     }
3968
3969   return(0);
3970 }
3971
3972 int check_user(LDAP *ldap_handle, char *dn_path, char *UserName, char *MoiraId)
3973 {
3974   char filter[128];
3975   char *attr_array[3];
3976   char SamAccountName[64];
3977   int  group_count;
3978   int  rc;
3979   LK_ENTRY  *group_base;
3980   LK_ENTRY  *gPtr;
3981
3982   group_count = 0;
3983   group_base = NULL;
3984
3985   if (strlen(MoiraId) != 0)
3986     {
3987       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
3988       attr_array[0] = "sAMAccountName";
3989       attr_array[1] = NULL;
3990       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3991                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3992         {
3993           com_err(whoami, 0, "Unable to process user %s : %s",
3994                   UserName, ldap_err2string(rc));
3995           return(rc);
3996         }
3997       if (group_count > 1)
3998         {
3999           com_err(whoami, 0, "multiple users exist with MoiraId = %s",
4000                   MoiraId);
4001           gPtr = group_base;
4002           while (gPtr)
4003             {
4004               com_err(whoami, 0, "user %s exist with MoiraId = %s",
4005                       gPtr->value, MoiraId);
4006               gPtr = gPtr->next;
4007             }
4008         }
4009     }
4010   if (group_count != 1)
4011     {
4012       linklist_free(group_base);
4013       group_count = 0;
4014       group_base = NULL;
4015       sprintf(filter, "(sAMAccountName=%s)", UserName);
4016       attr_array[0] = "sAMAccountName";
4017       attr_array[1] = NULL;
4018       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4019                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
4020         {
4021           com_err(whoami, 0, "Unable to process user %s : %s",
4022                   UserName, ldap_err2string(rc));
4023           return(rc);
4024         }
4025     }
4026
4027   if (group_count != 1)
4028     {
4029       linklist_free(group_base);
4030       return(AD_NO_USER_FOUND);
4031     }
4032   strcpy(SamAccountName, group_base->value);
4033   linklist_free(group_base);
4034   group_count = 0;
4035   rc = 0;
4036   if (strcmp(SamAccountName, UserName))
4037     {
4038       rc = user_rename(ldap_handle, dn_path, SamAccountName, 
4039                        UserName);
4040     }
4041   return(0);
4042 }
4043
4044 void container_get_dn(char *src, char *dest)
4045 {
4046   char *sPtr;
4047   char *array[20];
4048   char name[256];
4049   int  n;
4050
4051   memset(array, '\0', 20 * sizeof(array[0]));
4052
4053   if (strlen(src) == 0)
4054     return;
4055   strcpy(name, src);
4056   sPtr = name;
4057   n = 0;
4058   array[n] = name;
4059   ++n;
4060   while (*sPtr)
4061     {
4062       if ((*sPtr) == '/')
4063         {
4064           (*sPtr) = '\0';
4065           ++sPtr;
4066           array[n] = sPtr;
4067           ++n;
4068         }
4069       else
4070         ++sPtr;
4071     }
4072   strcpy(dest, "OU=");
4073   while (n != 0)
4074     {
4075       strcat(dest, array[n-1]);
4076       --n;
4077       if (n > 0)
4078         {
4079           strcat(dest, ",OU=");
4080         }
4081     }
4082   return;
4083 }
4084
4085 void container_get_name(char *src, char *dest)
4086 {
4087   char *sPtr;
4088   char *dPtr;
4089
4090   if (strlen(src) == 0)
4091     return;
4092   sPtr = src;
4093   dPtr = src;
4094   while (*sPtr)
4095     {
4096       if ((*sPtr) == '/')
4097         {
4098           dPtr = sPtr;
4099           ++dPtr;
4100         }
4101       ++sPtr;
4102     }
4103   strcpy(dest, dPtr);
4104   return;
4105 }
4106
4107 void container_check(LDAP *ldap_handle, char *dn_path, char *name)
4108 {
4109   char cName[256];
4110   char *av[7];
4111   int  i;
4112   int  rc;
4113
4114   strcpy(cName, name);
4115   for (i = 0; i < (int)strlen(cName); i++)
4116     {
4117       if (cName[i] == '/')
4118         {
4119           cName[i] = '\0';
4120           av[CONTAINER_NAME] = cName;
4121           av[CONTAINER_DESC] = "";
4122           av[CONTAINER_LOCATION] = "";
4123           av[CONTAINER_CONTACT] = "";
4124           av[CONTAINER_TYPE] = "";
4125           av[CONTAINER_ID] = "";
4126           av[CONTAINER_ROWID] = "";
4127           rc = container_create(ldap_handle, dn_path, 7, av);
4128           if (rc == LDAP_SUCCESS)
4129             {
4130               com_err(whoami, 0, "container %s created without a mitMoiraId", cName);
4131             }
4132           cName[i] = '/';
4133         }
4134     }
4135
4136 }
4137
4138 int container_rename(LDAP *ldap_handle, char *dn_path, int beforec, char **before, 
4139                      int afterc, char **after)
4140 {
4141   char      dName[256];
4142   char      cName[256];
4143   char      new_cn[128];
4144   char      new_dn_path[256];
4145   char      temp[256];
4146   char      distinguishedName[256];
4147   char      *pPtr;
4148   int       rc;
4149   int       i;
4150
4151   memset(cName, '\0', sizeof(cName));
4152   container_get_name(after[CONTAINER_NAME], cName);
4153   if (!check_container_name(cName))
4154     {
4155       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", cName);
4156       return(AD_INVALID_NAME);
4157     }
4158
4159   memset(distinguishedName, '\0', sizeof(distinguishedName));
4160   if (rc = container_get_distinguishedName(ldap_handle, dn_path, distinguishedName, beforec, before))
4161     return(rc);
4162   if (strlen(distinguishedName) == 0)
4163     {
4164       rc = container_create(ldap_handle, dn_path, afterc, after);
4165       return(rc);
4166     }
4167
4168   strcpy(temp, after[CONTAINER_NAME]);
4169   pPtr = temp;
4170   for (i = 0; i < (int)strlen(temp); i++)
4171     {
4172       if (temp[i] == '/')
4173         {
4174           pPtr = &temp[i];
4175         }
4176     }
4177   (*pPtr) = '\0';
4178
4179   container_get_dn(temp, dName);
4180   if (strlen(temp) != 0)
4181     sprintf(new_dn_path, "%s,%s", dName, dn_path);
4182   else
4183     sprintf(new_dn_path, "%s", dn_path);
4184   sprintf(new_cn, "OU=%s", cName);
4185
4186   container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
4187
4188   if ((rc = ldap_rename_s(ldap_handle, distinguishedName, new_cn, new_dn_path,
4189                           TRUE, NULL, NULL)) != LDAP_SUCCESS)
4190     {
4191       com_err(whoami, 0, "Unable to rename container from %s to %s : %s",
4192               before[CONTAINER_NAME], after[CONTAINER_NAME], ldap_err2string(rc));
4193       return(rc);
4194     }
4195
4196   memset(dName, '\0', sizeof(dName));
4197   container_get_dn(after[CONTAINER_NAME], dName);
4198   rc = container_adupdate(ldap_handle, dn_path, dName, "", afterc, after);
4199   return(rc);
4200 }
4201
4202 int container_delete(LDAP *ldap_handle, char *dn_path, int count, char **av)
4203 {
4204   char      distinguishedName[256];
4205   int       rc;
4206
4207   memset(distinguishedName, '\0', sizeof(distinguishedName));
4208   if (rc = container_get_distinguishedName(ldap_handle, dn_path, distinguishedName, count, av))
4209     return(rc);
4210   if (strlen(distinguishedName) == 0)
4211     return(0);
4212   if ((rc = ldap_delete_s(ldap_handle, distinguishedName)) != LDAP_SUCCESS)
4213     {
4214       if (rc == LDAP_NOT_ALLOWED_ON_NONLEAF)
4215         container_move_objects(ldap_handle, dn_path, distinguishedName);
4216       else
4217         com_err(whoami, 0, "Unable to delete container %s from AD : %s",
4218                 av[CONTAINER_NAME], ldap_err2string(rc));
4219     }
4220   return(rc);
4221 }
4222
4223 int container_create(LDAP *ldap_handle, char *dn_path, int count, char **av)
4224 {
4225   char      *attr_array[3];
4226   LK_ENTRY  *group_base;
4227   int       group_count;
4228   LDAPMod   *mods[20];
4229   char      *objectClass_v[] = {"top", 
4230                            "organizationalUnit", 
4231                            NULL};
4232
4233   char *ou_v[] = {NULL, NULL};
4234   char *name_v[] = {NULL, NULL};
4235   char *moiraId_v[] = {NULL, NULL};
4236   char *desc_v[] = {NULL, NULL};
4237   char *managedBy_v[] = {NULL, NULL};
4238   char dName[256];
4239   char cName[256];
4240   char managedByDN[256];
4241   char filter[256];
4242   char temp[256];
4243   int  n;
4244   int  i;
4245   int  rc;
4246
4247   memset(filter, '\0', sizeof(filter));
4248   memset(dName, '\0', sizeof(dName));
4249   memset(cName, '\0', sizeof(cName));
4250   memset(managedByDN, '\0', sizeof(managedByDN));
4251   container_get_dn(av[CONTAINER_NAME], dName);
4252   container_get_name(av[CONTAINER_NAME], cName);
4253
4254   if ((strlen(cName) == 0) || (strlen(dName) == 0))
4255     {
4256       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", cName);
4257       return(AD_INVALID_NAME);
4258     }
4259
4260   if (!check_container_name(cName))
4261     {
4262       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", cName);
4263       return(AD_INVALID_NAME);
4264     }
4265
4266   n = 0;
4267   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
4268   name_v[0] = cName;
4269   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
4270   ou_v[0] = cName;
4271   ADD_ATTR("ou", ou_v, LDAP_MOD_ADD);
4272   if (strlen(av[CONTAINER_ROWID]) != 0)
4273     {
4274       moiraId_v[0] = av[CONTAINER_ROWID];
4275       ADD_ATTR("mitMoiraId", moiraId_v, LDAP_MOD_ADD);
4276     }
4277   if (strlen(av[CONTAINER_DESC]) != 0)
4278     {
4279       desc_v[0] = av[CONTAINER_DESC];
4280       ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
4281     }
4282   if ((strlen(av[CONTAINER_TYPE]) != 0) && (strlen(av[CONTAINER_ID]) != 0))
4283     {
4284           if (!strcasecmp(av[CONTAINER_TYPE], "KERBEROS"))
4285           {
4286                   if (!contact_create(ldap_handle, dn_path, av[CONTAINER_ID], kerberos_ou))
4287                   {
4288                         sprintf(managedByDN, "CN=%s,%s,%s", av[CONTAINER_ID], kerberos_ou,dn_path);
4289                         managedBy_v[0] = managedByDN;
4290                         ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_ADD);
4291                   }
4292           }
4293           else
4294           {
4295                 if (!strcasecmp(av[CONTAINER_TYPE], "USER"))
4296         {
4297           sprintf(filter, "(&(cn=%s)(&(objectCategory=person)(objectClass=user)))", av[CONTAINER_ID]);
4298         }
4299                 if (!strcasecmp(av[CONTAINER_TYPE], "LIST"))
4300         {
4301           sprintf(filter, "(&(objectClass=group)(cn=%s))", av[CONTAINER_ID]);
4302         }
4303                 if (strlen(filter) != 0)
4304         {
4305           attr_array[0] = "distinguishedName";
4306           attr_array[1] = NULL;
4307           group_count = 0;
4308           group_base = NULL;
4309           if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4310                                    &group_base, &group_count, LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
4311             {
4312               if (group_count == 1)
4313                 {
4314                   strcpy(managedByDN, group_base->value);
4315                   managedBy_v[0] = managedByDN;
4316                   ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_ADD);
4317                 }
4318               linklist_free(group_base);
4319               group_base = NULL;
4320               group_count = 0;
4321             }
4322         }
4323     }
4324   }
4325   mods[n] = NULL;
4326
4327   sprintf(temp, "%s,%s", dName, dn_path);
4328   rc = ldap_add_ext_s(ldap_handle, temp, mods, NULL, NULL);
4329   for (i = 0; i < n; i++)
4330     free(mods[i]);
4331   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
4332     {
4333       com_err(whoami, 0, "Unable to create container %s : %s",
4334               cName, ldap_err2string(rc));
4335       return(rc);
4336     }
4337   if (rc == LDAP_ALREADY_EXISTS)
4338     {
4339       if (strlen(av[CONTAINER_ROWID]) != 0)
4340         rc = container_adupdate(ldap_handle, dn_path, dName, "", count, av);
4341     }
4342   return(rc);
4343 }
4344
4345 int container_update(LDAP *ldap_handle, char *dn_path, int beforec, char **before, 
4346                      int afterc, char **after)
4347 {
4348   char distinguishedName[256];
4349   int  rc;
4350
4351   memset(distinguishedName, '\0', sizeof(distinguishedName));
4352   if (rc = container_get_distinguishedName(ldap_handle, dn_path, distinguishedName, afterc, after))
4353     return(rc);
4354   if (strlen(distinguishedName) == 0)
4355     {
4356       rc = container_create(ldap_handle, dn_path, afterc, after);
4357       return(rc);
4358     }
4359
4360   container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
4361   rc = container_adupdate(ldap_handle, dn_path, "", distinguishedName, afterc, after);
4362
4363   return(rc);
4364 }
4365
4366 int container_get_distinguishedName(LDAP *ldap_handle, char *dn_path, char *distinguishedName, int count, char **av)
4367 {
4368   char      *attr_array[3];
4369   LK_ENTRY  *group_base;
4370   int       group_count;
4371   char      dName[256];
4372   char      cName[256];
4373   char      filter[512];
4374   int       rc;
4375
4376   memset(filter, '\0', sizeof(filter));
4377   memset(dName, '\0', sizeof(dName));
4378   memset(cName, '\0', sizeof(cName));
4379   container_get_dn(av[CONTAINER_NAME], dName);
4380   container_get_name(av[CONTAINER_NAME], cName);
4381
4382   if (strlen(dName) == 0)
4383     {
4384       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", av[CONTAINER_NAME]);
4385       return(AD_INVALID_NAME);
4386     }
4387
4388   if (!check_container_name(cName))
4389     {
4390       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", cName);
4391       return(AD_INVALID_NAME);
4392     }
4393
4394   sprintf(filter, "(&(objectClass=organizationalUnit)(mitMoiraId=%s))", av[CONTAINER_ROWID]);
4395   attr_array[0] = "distinguishedName";
4396   attr_array[1] = NULL;
4397   group_count = 0;
4398   group_base = NULL;
4399   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4400                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
4401     {
4402       if (group_count == 1)
4403         {
4404           strcpy(distinguishedName, group_base->value);
4405         }
4406       linklist_free(group_base);
4407       group_base = NULL;
4408       group_count = 0;
4409     }
4410   if (strlen(distinguishedName) == 0)
4411     {
4412       sprintf(filter, "(&(objectClass=organizationalUnit)(distinguishedName=%s,%s))", dName, dn_path);
4413       attr_array[0] = "distinguishedName";
4414       attr_array[1] = NULL;
4415       group_count = 0;
4416       group_base = NULL;
4417       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4418                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
4419         {
4420           if (group_count == 1)
4421             {
4422               strcpy(distinguishedName, group_base->value);
4423             }
4424           linklist_free(group_base);
4425           group_base = NULL;
4426           group_count = 0;
4427         }
4428     }
4429   return(0);
4430 }
4431
4432 int container_adupdate(LDAP *ldap_handle, char *dn_path, char *dName, 
4433                        char *distinguishedName, int count, char **av)
4434 {
4435   char      *attr_array[5];
4436   LK_ENTRY  *group_base;
4437   LK_ENTRY  *pPtr;
4438   LDAPMod   *mods[20];
4439   int       group_count;
4440   char      filter[512];
4441   char      *moiraId_v[] = {NULL, NULL};
4442   char      *desc_v[] = {NULL, NULL};
4443   char      *managedBy_v[] = {NULL, NULL};
4444   char      managedByDN[256];
4445   char      moiraId[64];
4446   char      desc[256];
4447   char      ad_path[512];
4448   int       rc;
4449   int       i;
4450   int       n;
4451
4452
4453   strcpy(ad_path, distinguishedName);
4454   if (strlen(dName) != 0)
4455     sprintf(ad_path, "%s,%s", dName, dn_path);
4456
4457   sprintf(filter, "(&(objectClass=organizationalUnit)(distinguishedName=%s))", ad_path);
4458   if (strlen(av[CONTAINER_ID]) != 0)
4459     sprintf(filter, "(&(objectClass=organizationalUnit)(mitMoiraId=%s))", av[CONTAINER_ROWID]);
4460   attr_array[0] = "mitMoiraId";
4461   attr_array[1] = "description";
4462   attr_array[2] = "managedBy";
4463   attr_array[3] = NULL;
4464   group_count = 0;
4465   group_base = NULL;
4466   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4467                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != LDAP_SUCCESS)
4468     {
4469       com_err(whoami, 0, "Unable to retreive container info for %s : %s",
4470               av[CONTAINER_NAME], ldap_err2string(rc));
4471       return(rc);
4472     }
4473   memset(managedByDN, '\0', sizeof(managedByDN));
4474   memset(moiraId, '\0', sizeof(moiraId));
4475   memset(desc, '\0', sizeof(desc));
4476   pPtr = group_base;
4477   while (pPtr)
4478     {
4479       if (!strcasecmp(pPtr->attribute, "description"))
4480         strcpy(desc, pPtr->value);
4481       else if (!strcasecmp(pPtr->attribute, "managedBy"))
4482         strcpy(managedByDN, pPtr->value);
4483       else if (!strcasecmp(pPtr->attribute, "mitMoiraId"))
4484         strcpy(moiraId, pPtr->value);
4485       pPtr = pPtr->next;
4486     }
4487   linklist_free(group_base);
4488   group_base = NULL;
4489   group_count = 0;
4490
4491   n = 0;
4492   if (strlen(av[CONTAINER_ROWID]) != 0)
4493     {
4494       moiraId_v[0] = av[CONTAINER_ROWID];
4495       ADD_ATTR("mitMoiraId", moiraId_v, LDAP_MOD_REPLACE);
4496     }
4497   if (strlen(av[CONTAINER_DESC]) != 0)
4498     {
4499       attribute_update(ldap_handle, ad_path, av[CONTAINER_DESC], "description", dName);
4500     }
4501   else
4502     {
4503       if (strlen(desc) != 0)
4504         {
4505           attribute_update(ldap_handle, ad_path, "", "description", dName);
4506         }
4507     }
4508   if ((strlen(av[CONTAINER_TYPE]) != 0) && (strlen(av[CONTAINER_ID]) != 0))
4509     {
4510           if (!strcasecmp(av[CONTAINER_TYPE], "KERBEROS"))
4511           {
4512                   if (!contact_create(ldap_handle, dn_path, av[CONTAINER_ID], kerberos_ou))
4513                   {
4514                         sprintf(managedByDN, "CN=%s,%s,%s", av[CONTAINER_ID], kerberos_ou, dn_path);
4515                         managedBy_v[0] = managedByDN;
4516             ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_REPLACE);
4517                   }
4518                   else
4519                   {
4520                         if (strlen(managedByDN) != 0)
4521                         {
4522                 attribute_update(ldap_handle, ad_path, "", "managedBy", dName);
4523                         }
4524                   }
4525           }
4526           else
4527           {
4528                 memset(filter, '\0', sizeof(filter));
4529                 if (!strcasecmp(av[CONTAINER_TYPE], "USER"))
4530         {
4531           sprintf(filter, "(&(cn=%s)(&(objectCategory=person)(objectClass=user)))", av[CONTAINER_ID]);
4532         }
4533                 if (!strcasecmp(av[CONTAINER_TYPE], "LIST"))
4534         {
4535           sprintf(filter, "(&(objectClass=group)(cn=%s))", av[CONTAINER_ID]);
4536         }
4537                 if (strlen(filter) != 0)
4538         {
4539           attr_array[0] = "distinguishedName";
4540           attr_array[1] = NULL;
4541           group_count = 0;
4542           group_base = NULL;
4543           if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4544                                    &group_base, &group_count, LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
4545             {
4546               if (group_count == 1)
4547                 {
4548                   strcpy(managedByDN, group_base->value);
4549                   managedBy_v[0] = managedByDN;
4550                   ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_REPLACE);
4551                 }
4552               else
4553                 {
4554                   if (strlen(managedByDN) != 0)
4555                     {
4556                         attribute_update(ldap_handle, ad_path, "", "managedBy", dName);
4557                     }
4558                 }
4559               linklist_free(group_base);
4560               group_base = NULL;
4561               group_count = 0;
4562             }
4563         }
4564                 else
4565         {
4566           if (strlen(managedByDN) != 0)
4567             {
4568                 attribute_update(ldap_handle, ad_path, "", "managedBy", dName);
4569             }
4570         }
4571           }
4572     }
4573   mods[n] = NULL;
4574   if (n == 0)
4575     return(LDAP_SUCCESS);
4576
4577   rc = ldap_modify_s(ldap_handle, ad_path, mods);
4578   for (i = 0; i < n; i++)
4579     free(mods[i]);
4580   if (rc != LDAP_SUCCESS)
4581     {
4582         com_err(whoami, 0, "Unable to modify container info for %s : %s",
4583                 av[CONTAINER_NAME], ldap_err2string(rc));
4584         return(rc);
4585     }
4586   return(rc);
4587 }
4588
4589 int container_move_objects(LDAP *ldap_handle, char *dn_path, char *dName)
4590 {
4591   char      *attr_array[3];
4592   LK_ENTRY  *group_base;
4593   LK_ENTRY  *pPtr;
4594   int       group_count;
4595   char      filter[512];
4596   char      new_cn[128];
4597   char      temp[256];
4598   int       rc;
4599   int       NumberOfEntries = 10;
4600   int       i;
4601   int       count;
4602
4603   rc = ldap_set_option(ldap_handle, LDAP_OPT_SIZELIMIT, &NumberOfEntries);
4604
4605   for (i = 0; i < 3; i++)
4606     {
4607       memset(filter, '\0', sizeof(filter));
4608       if (i == 0)
4609         {
4610           strcpy(filter, "(!(|(objectClass=computer)(objectClass=organizationalUnit)))");
4611           attr_array[0] = "cn";
4612           attr_array[1] = NULL;
4613         }
4614       else if (i == 1)
4615         {
4616           strcpy(filter, "(objectClass=computer)");
4617           attr_array[0] = "cn";
4618           attr_array[1] = NULL;
4619         }
4620       else
4621         {
4622           strcpy(filter, "(objectClass=organizationalUnit)");
4623           attr_array[0] = "ou";
4624           attr_array[1] = NULL;
4625         }
4626
4627       while (1)
4628         {
4629           if ((rc = linklist_build(ldap_handle, dName, filter, attr_array, 
4630                                    &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != LDAP_SUCCESS)
4631             {
4632               break;
4633             }
4634           if (group_count == 0)
4635             break;
4636           pPtr = group_base;
4637           while(pPtr)
4638             {
4639               if (!strcasecmp(pPtr->attribute, "cn"))
4640                 {
4641                   sprintf(new_cn, "cn=%s", pPtr->value);
4642                   if (i == 0)
4643                     sprintf(temp, "%s,%s", orphans_other_ou, dn_path);
4644                   if (i == 1)
4645                     sprintf(temp, "%s,%s", orphans_machines_ou, dn_path);
4646                   count = 1;
4647                   while (1)
4648                     {
4649                       rc = ldap_rename_s(ldap_handle, pPtr->dn, new_cn, temp,
4650                                          TRUE, NULL, NULL);
4651                       if (rc == LDAP_ALREADY_EXISTS)
4652                         {
4653                           sprintf(new_cn, "cn=%s_%d", pPtr->value, count);
4654                           ++count;
4655                         }
4656                       else
4657                         break;
4658                     }
4659                 }
4660               else if (!strcasecmp(pPtr->attribute, "ou"))
4661                 {
4662                   rc = ldap_delete_s(ldap_handle, pPtr->dn);
4663                 }
4664               pPtr = pPtr->next;
4665             }
4666           linklist_free(group_base);
4667           group_base = NULL;
4668           group_count = 0;
4669         }
4670     }
4671   return(0);
4672 }
4673
4674 int get_machine_ou(LDAP *ldap_handle, char *dn_path, char *member, char *machine_ou, char *NewMachineName)
4675 {
4676   LK_ENTRY  *group_base;
4677   int  group_count;
4678   int  i;
4679   char filter[128];
4680   char *attr_array[3];
4681   char cn[256];
4682   char dn[256];
4683   char temp[256];
4684   char *pPtr;
4685   int   rc;
4686
4687   strcpy(NewMachineName, member);
4688   rc = moira_connect();
4689   rc = GetMachineName(NewMachineName);
4690   moira_disconnect();
4691   if (strlen(NewMachineName) == 0)
4692     {
4693       com_err(whoami, 0, "Unable to find alais for machine %s in Moira", member);
4694       return(1);
4695     }
4696
4697   pPtr = NULL;
4698   pPtr = strchr(NewMachineName, '.');
4699   if (pPtr != NULL)
4700     (*pPtr) = '\0';
4701
4702   group_base = NULL;
4703   group_count = 0;
4704   sprintf(filter, "(sAMAccountName=%s$)", NewMachineName);
4705   attr_array[0] = "cn";
4706   attr_array[1] = NULL;
4707   sprintf(temp, "%s", dn_path);
4708   if ((rc = linklist_build(ldap_handle, temp, filter, attr_array, 
4709                         &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
4710     {
4711       com_err(whoami, 0, "Unable to process machine %s : %s",
4712               member, ldap_err2string(rc));
4713       return(1);
4714     }
4715   if (group_count != 1)
4716     {
4717       com_err(whoami, 0, "Unable to process machine %s : machine not found in AD",
4718               NewMachineName);
4719       return(1);
4720     }
4721   strcpy(dn, group_base->dn);
4722   strcpy(cn, group_base->value);
4723   for (i = 0; i < (int)strlen(dn); i++)
4724     dn[i] = tolower(dn[i]);
4725   for (i = 0; i < (int)strlen(cn); i++)
4726     cn[i] = tolower(cn[i]);
4727   linklist_free(group_base);
4728   pPtr = NULL;
4729   pPtr = strstr(dn, cn);
4730   if (pPtr == NULL)
4731     {
4732       com_err(whoami, 0, "Unable to process machine %s",
4733               member);
4734       return(1);
4735     }
4736   pPtr += strlen(cn) + 1;
4737   strcpy(machine_ou, pPtr);
4738   pPtr = NULL;
4739   pPtr = strstr(machine_ou, "dc=");
4740   if (pPtr == NULL)
4741     {
4742       com_err(whoami, 0, "Unable to process machine %s",
4743               member);
4744       return(1);
4745     }
4746   --pPtr;
4747   (*pPtr) = '\0';
4748   return(0);
4749 }
4750
4751 int machine_move_to_ou(LDAP *ldap_handle, char * dn_path, char *MoiraMachineName, char *DestinationOu)
4752 {
4753
4754     char        NewCn[128];
4755     char        OldDn[512];
4756     char        MachineName[128];
4757     char        filter[128];
4758     char        *attr_array[3];
4759     char        NewOu[256];
4760     char        *cPtr = NULL;
4761     int         group_count;
4762     long        rc;
4763     LK_ENTRY    *group_base;
4764
4765     group_count = 0;
4766     group_base = NULL;
4767
4768     strcpy(MachineName, MoiraMachineName);
4769     rc = GetMachineName(MachineName);
4770     if (strlen(MachineName) == 0)
4771     {
4772         com_err(whoami, 0, "Unable to find alais for machine %s in Moira", MoiraMachineName);
4773         return(1);
4774     }
4775
4776     cPtr = strchr(MachineName, '.');
4777     if (cPtr != NULL)
4778         (*cPtr) = '\0';
4779     sprintf(filter, "(sAMAccountName=%s$)", MachineName);
4780     attr_array[0] = "sAMAccountName";
4781     attr_array[1] = NULL;
4782     if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, &group_base, 
4783                              &group_count, LDAP_SCOPE_SUBTREE)) != 0)
4784     {
4785         com_err(whoami, 0, "Unable to process machine %s : %s",
4786                 MoiraMachineName, ldap_err2string(rc));
4787         return(1);
4788     }
4789
4790     if (group_count == 1)
4791         strcpy(OldDn, group_base->dn);
4792     linklist_free(group_base);
4793     group_base = NULL;
4794     if (group_count != 1)
4795     {
4796         com_err(whoami, 0, "Unable to find machine %s in AD: %s", MoiraMachineName);
4797         return(1);
4798     }
4799     sprintf(NewOu, "%s,%s", DestinationOu, dn_path);
4800     cPtr = strchr(OldDn, ',');
4801     if (cPtr != NULL)
4802     {
4803         ++cPtr;
4804         if (!strcasecmp(cPtr, NewOu))
4805             return(0);
4806     }
4807     sprintf(NewCn, "CN=%s", MachineName);
4808     rc = ldap_rename_s(ldap_handle, OldDn, NewCn, NewOu, TRUE, NULL, NULL);
4809     return(rc);
4810 }
4811
4812 int machine_check(LDAP *ldap_handle, char *dn_path, char *machine_name)
4813 {
4814     char    Name[128];
4815     char    *pPtr;
4816     int     rc;
4817
4818     memset(Name, '\0', sizeof(Name));
4819     strcpy(Name, machine_name);
4820     pPtr = NULL;
4821     pPtr = strchr(Name, '.');
4822     if (pPtr != NULL)
4823         (*pPtr) = '\0';
4824     strcat(Name, "$");
4825     return(!(rc = checkADname(ldap_handle, dn_path, Name)));
4826 }
4827
4828 int machine_get_moira_container(LDAP *ldap_handle, char *dn_path, char *machine_name, char *container_name)
4829 {
4830     int     rc;
4831     char    *av[2];
4832     char    *call_args[2];
4833
4834     av[0] = machine_name;
4835     call_args[0] = (char *)container_name;
4836     rc = mr_query("get_machine_to_container_map", 1, av, machine_GetMoiraContainer,
4837                    call_args);
4838     return(rc);
4839 }
4840
4841 int machine_GetMoiraContainer(int ac, char **av, void *ptr)
4842 {
4843     char **call_args;
4844     
4845     call_args = ptr;
4846     strcpy(call_args[0], av[1]);
4847     return(0);
4848 }
4849
4850 int Moira_container_group_create(char **after)
4851 {
4852   long rc;
4853   char GroupName[64];
4854   char *argv[20];
4855   
4856   memset(GroupName, '\0', sizeof(GroupName));
4857   rc = Moira_groupname_create(GroupName, after[CONTAINER_NAME], 
4858                               after[CONTAINER_ROWID]);
4859   if (rc)
4860     return rc;
4861   
4862   argv[L_NAME] = GroupName;
4863   argv[L_ACTIVE] = "1";
4864   argv[L_PUBLIC] = "0";
4865   argv[L_HIDDEN] = "0";
4866   argv[L_MAILLIST] = "0";
4867   argv[L_GROUP] = "1";
4868   argv[L_GID] = UNIQUE_GID;
4869   argv[L_NFSGROUP] = "0";
4870   argv[L_MAILMAN] = "0";
4871   argv[L_MAILMAN_SERVER] = "[NONE]";
4872   argv[L_DESC] = "auto created container group";
4873   argv[L_ACE_TYPE] = "USER";
4874   argv[L_MEMACE_TYPE] = "USER";
4875   argv[L_ACE_NAME] = "sms";
4876   argv[L_MEMACE_NAME] = "sms";
4877
4878   if (rc = mr_query("add_list", 15, argv, NULL, NULL))
4879     {
4880       com_err(whoami, 0, "Unable to create container group %s for container %s: %s",
4881               GroupName, after[CONTAINER_NAME], error_message(rc));
4882     }
4883
4884   Moira_setContainerGroup(after[CONTAINER_NAME], GroupName);
4885   Moira_addGroupToParent(after[CONTAINER_NAME], GroupName);
4886   
4887   return(rc);
4888 }
4889
4890 int Moira_container_group_update(char **before, char **after)
4891 {
4892   long rc;
4893   char BeforeGroupName[64];
4894   char AfterGroupName[64];
4895   char *argv[20];
4896   
4897   if (!strcasecmp(after[CONTAINER_NAME], before[CONTAINER_NAME]))
4898     return(0);
4899
4900   memset(BeforeGroupName, '\0', sizeof(BeforeGroupName));
4901   Moira_getGroupName(after[CONTAINER_NAME], BeforeGroupName, 0);
4902   if (strlen(BeforeGroupName) == 0)
4903     return(0);
4904
4905   memset(AfterGroupName, '\0', sizeof(AfterGroupName));
4906   rc = Moira_groupname_create(AfterGroupName, after[CONTAINER_NAME], 
4907                               after[CONTAINER_ROWID]);
4908   if (rc)
4909     return rc;
4910
4911   if (strcasecmp(BeforeGroupName, AfterGroupName))
4912     {
4913       argv[L_NAME] = BeforeGroupName;
4914       argv[L_NAME + 1] = AfterGroupName;
4915       argv[L_ACTIVE + 1] = "1";
4916       argv[L_PUBLIC + 1] = "0";
4917       argv[L_HIDDEN + 1] = "0";
4918       argv[L_MAILLIST + 1] = "0";
4919       argv[L_GROUP + 1] = "1";
4920       argv[L_GID + 1] = UNIQUE_GID;
4921       argv[L_NFSGROUP + 1] = "0";
4922       argv[L_MAILMAN + 1] = "0";
4923       argv[L_MAILMAN_SERVER + 1] = "[NONE]";
4924       argv[L_DESC + 1] = "auto created container group";
4925       argv[L_ACE_TYPE + 1] = "USER";
4926       argv[L_MEMACE_TYPE + 1] = "USER";
4927       argv[L_ACE_NAME + 1] = "sms";
4928       argv[L_MEMACE_NAME + 1] = "sms";
4929       
4930       if (rc = mr_query("update_list", 16, argv, NULL, NULL))
4931         {
4932           com_err(whoami, 0, "Unable to rename container group from %s to %s: %s",
4933                   BeforeGroupName, AfterGroupName, error_message(rc));
4934         }
4935     }
4936   
4937   return(rc);
4938 }
4939
4940 int Moira_container_group_delete(char **before)
4941 {
4942   long rc = 0;
4943   char *argv[13];
4944   char GroupName[64];
4945   char ParentGroupName[64];
4946   
4947   memset(ParentGroupName, '\0', sizeof(ParentGroupName));
4948   Moira_getGroupName(before[CONTAINER_NAME], ParentGroupName, 1);
4949
4950   memset(GroupName, '\0', sizeof(GroupName));
4951   if (strcmp(before[CONTAINER_GROUP_NAME], "[none]"))
4952     strcpy(GroupName, before[CONTAINER_GROUP_NAME]);
4953   
4954   if ((strlen(ParentGroupName) != 0) && (strlen(GroupName) != 0))
4955     {
4956       argv[0] = ParentGroupName;
4957       argv[1] = "LIST";
4958       argv[2] = GroupName;
4959       if (rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL))
4960         {
4961           com_err(whoami, 0, "Unable to delete container group %s from list: %s",
4962                   GroupName, ParentGroupName, error_message(rc));
4963         }
4964     }
4965   
4966   if (strlen(GroupName) != 0)
4967     {
4968       argv[0] = GroupName;
4969       if (rc = mr_query("delete_list", 1, argv, NULL, NULL))
4970         {
4971           com_err(whoami, 0, "Unable to delete container group %s : %s",
4972                   GroupName, error_message(rc));
4973         }
4974      }
4975   
4976   return(rc);
4977 }
4978
4979 int Moira_groupname_create(char *GroupName, char *ContainerName,
4980                            char *ContainerRowID)
4981 {
4982   char *ptr;
4983   char *ptr1;
4984   char temp[64];
4985   char newGroupName[64];
4986   char tempGroupName[64];
4987   char tempgname[64];
4988   char *argv[1];
4989   int  i;
4990   long rc;
4991
4992   strcpy(temp, ContainerName);
4993   
4994   ptr1 = strrchr(temp, '/');
4995   if (ptr1 != NULL)
4996   {
4997     *ptr1 = '\0';
4998     ptr = ++ptr1;
4999     ptr1 = strrchr(temp, '/');
5000     if (ptr1 != NULL)
5001     {
5002         sprintf(tempgname, "%s-%s", ++ptr1, ptr);
5003     }
5004     else
5005         strcpy(tempgname, ptr);
5006   }
5007   else
5008     strcpy(tempgname, temp);
5009
5010   if (strlen(tempgname) > 25)
5011     tempgname[25] ='\0';
5012
5013   sprintf(newGroupName, "cnt-%s", tempgname);
5014
5015   /* change everything to lower case */
5016   ptr = newGroupName;
5017   while (*ptr)
5018     {
5019       if (isupper(*ptr))
5020         *ptr = tolower(*ptr);
5021       if (*ptr == ' ')
5022         *ptr = '-';
5023       ptr++;
5024     }
5025
5026   strcpy(tempGroupName, newGroupName);
5027   i = (int)'0';
5028   /* append 0-9 then a-z if a duplicate is found */
5029   while(1)
5030     {
5031       argv[0] = newGroupName;
5032       if (rc = mr_query("get_list_info", 1, argv, NULL, NULL))
5033         {
5034           if (rc == MR_NO_MATCH)
5035             break;
5036           com_err(whoami, 0, "Moira error while creating group name for container %s : %s",
5037                   ContainerName, error_message(rc));
5038           return rc;
5039         }
5040       sprintf(newGroupName, "%s-%c", tempGroupName, i);
5041       if (i == (int)'z')
5042         {
5043           com_err(whoami, 0, "Unable to find a unique group name for container %s: too many duplicate container names",
5044                   ContainerName);
5045           return 1;
5046         }
5047       if (i == '9')
5048         i = 'a';
5049       else
5050         i++;
5051     }
5052
5053   strcpy(GroupName, newGroupName);
5054   return(0);
5055 }
5056
5057 int Moira_setContainerGroup(char *origContainerName, char *GroupName)
5058 {
5059   long rc;
5060   char *argv[3];
5061   
5062   argv[0] = origContainerName;
5063   argv[1] = GroupName;
5064
5065   if ((rc = mr_query("set_container_list", 2, argv, NULL, NULL)))
5066     {
5067          com_err(whoami, 0, "Unable to set container group %s in container %s: %s",
5068                  GroupName, origContainerName, error_message(rc));
5069     }
5070
5071   return(0);
5072 }
5073
5074  int Moira_addGroupToParent(char *origContainerName, char *GroupName)
5075  {
5076    char ContainerName[64];
5077    char ParentGroupName[64];
5078    char *argv[3];
5079    long rc;
5080
5081    strcpy(ContainerName, origContainerName);
5082
5083    Moira_getGroupName(ContainerName, ParentGroupName, 1);
5084    /* top-level container */
5085    if (strlen(ParentGroupName) == 0)
5086      return(0);
5087    
5088    argv[0] = ParentGroupName;
5089    argv[1] = "LIST";
5090    argv[2] = GroupName;
5091    if ((rc = mr_query("add_member_to_list", 3, argv, NULL, NULL)))
5092      {
5093        com_err(whoami, 0, "Unable to add container group %s to parent group %s: %s",
5094                GroupName, ParentGroupName, error_message(rc));
5095      }
5096    return(0);
5097  }
5098
5099 int Moira_getContainerGroup(int ac, char **av, void *ptr)
5100 {
5101   char **call_args;
5102   
5103   call_args = ptr;
5104   strcpy(call_args[0], av[1]);
5105   return(0);
5106 }
5107
5108 int Moira_getGroupName(char *origContainerName, char *GroupName,
5109                        int ParentFlag)
5110 {
5111   char ContainerName[64];
5112   char *argv[3];
5113   char *call_args[3];
5114   char *ptr;
5115   long rc;
5116
5117   strcpy(ContainerName, origContainerName);
5118
5119   if (ParentFlag)
5120     {
5121       ptr = strrchr(ContainerName, '/');
5122       if (ptr != NULL)
5123         (*ptr) = '\0';
5124       else
5125         return(0);
5126     }
5127
5128   argv[0] = ContainerName;
5129   argv[1] = NULL;
5130   call_args[0] = GroupName;
5131   call_args[1] = NULL;
5132
5133   if (!(rc = mr_query("get_container_list", 1, argv, Moira_getContainerGroup,
5134                       call_args)))
5135     {
5136       if (strlen(GroupName) != 0)
5137         return(0);
5138     }
5139
5140   if (rc)
5141     com_err(whoami, 0, "Unable to get container group from container %s: %s",
5142             ContainerName, error_message(rc));
5143   else
5144     com_err(whoami, 0, "Unable to get container group from container %s",
5145             ContainerName);
5146      return(0);
5147 }
5148
5149 int Moira_process_machine_container_group(char *MachineName, char* GroupName, 
5150                                           int DeleteMachine)
5151 {
5152   char *argv[3];
5153   long rc;
5154
5155   if (strcmp(GroupName, "[none]") == 0)
5156     return 0;
5157
5158   argv[0] = GroupName;
5159   argv[1] = "MACHINE";
5160   argv[2] = MachineName;
5161   if (!DeleteMachine)
5162     rc = mr_query("add_member_to_list", 3, argv, NULL, NULL);
5163   else
5164     rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL);
5165   if (rc)
5166     {
5167       com_err(whoami, 0, "Unable to add machine %s to container group%s: %s",
5168               MachineName, GroupName, error_message(rc));
5169     }
5170   return(0);
5171 }
5172
5173 int GetMachineName(char *MachineName)
5174 {
5175         char    *args[2];
5176     char    NewMachineName[1024];
5177     char    *szDot;
5178     int     rc = 0;
5179     int     i;
5180     DWORD   dwLen = 0;
5181     char    *call_args[2];
5182
5183     // If the address happens to be in the top-level MIT domain, great!
5184     strcpy(NewMachineName, MachineName);
5185     for (i = 0; i < (int)strlen(NewMachineName); i++)
5186         NewMachineName[i] = toupper(NewMachineName[i]);
5187     szDot = strchr(NewMachineName,'.');
5188     if ((szDot) && (!strcasecmp(szDot+1, DOMAIN_SUFFIX)))
5189     {
5190         return(0);
5191     }
5192         
5193     // If not, see if it has a Moira alias in the top-level MIT domain.
5194     memset(NewMachineName, '\0', sizeof(NewMachineName));
5195         args[0] = "*";
5196     args[1] = MachineName;
5197     call_args[0] = NewMachineName;
5198     call_args[1] = NULL;
5199     if (rc = mr_query("get_hostalias", 2, args, ProcessMachineName, call_args))
5200     {
5201         com_err(whoami, 0, "Unable to resolve machine name %s : %s",
5202                 MachineName, error_message(rc));
5203         strcpy(MachineName, "");
5204         return(0);
5205     }
5206
5207     if (strlen(NewMachineName) != 0)
5208         strcpy(MachineName, NewMachineName);
5209     else
5210         strcpy(MachineName, "");
5211     return(0);
5212
5213 }
5214
5215 int ProcessMachineName(int ac, char **av, void *ptr)
5216 {
5217     char    **call_args;
5218     char    MachineName[1024];
5219     char    *szDot;
5220     int     i;
5221
5222     call_args = ptr;
5223     if (strlen(call_args[0]) == 0)
5224     {
5225         strcpy(MachineName, av[0]);
5226         for (i = 0; i < (int)strlen(MachineName); i++)
5227             MachineName[i] = toupper(MachineName[i]);
5228         szDot = strchr(MachineName,'.');
5229         if ((szDot) && (!strcasecmp(szDot+1,DOMAIN_SUFFIX)))
5230         {
5231             strcpy(call_args[0], MachineName);
5232         }
5233     }
5234     return(0);
5235 }
5236
5237 void SwitchSFU(LDAPMod **mods, int *UseSFU30, int n)
5238 {
5239     int i;
5240
5241     if (*UseSFU30)
5242     {
5243         for (i = 0; i < n; i++)
5244         {
5245             if (!strcmp(mods[i]->mod_type, "msSFU30UidNumber"))
5246                 mods[i]->mod_type = "uidNumber";
5247         }
5248         (*UseSFU30) = 0;
5249     }
5250     else
5251     {
5252         for (i = 0; i < n; i++)
5253         {
5254             if (!strcmp(mods[i]->mod_type, "uidNumber"))
5255                 mods[i]->mod_type = "msSFU30UidNumber";
5256         }
5257         (*UseSFU30) = 1;
5258     }
5259 }
5260
5261 int SetHomeDirectory(LDAP *ldap_handle, char *user_name, char *DistinguishedName,
5262                      char *WinHomeDir, char *WinProfileDir,
5263                      char **homedir_v, char **winProfile_v,
5264                      char **drives_v, LDAPMod **mods, 
5265                      int OpType, int n)
5266 {
5267     char **hp;
5268     char cWeight[3];
5269     char cPath[1024];
5270     char path[1024];
5271     char winPath[1024];
5272     char winProfile[1024];
5273     char homeDrive[8];
5274     int  last_weight;
5275     int  i;
5276     int  rc;
5277     LDAPMod *DelMods[20];
5278
5279     memset(homeDrive, '\0', sizeof(homeDrive));
5280     memset(path, '\0', sizeof(path));
5281     memset(winPath, '\0', sizeof(winPath));
5282     memset(winProfile, '\0', sizeof(winProfile));
5283     hp = NULL;
5284     if ((!strcasecmp(WinHomeDir, "[afs]")) || (!strcasecmp(WinProfileDir, "[afs]")))
5285     {
5286         if ((hp = hes_resolve(user_name, "filsys")) != NULL)
5287         {
5288             memset(cWeight, 0, sizeof(cWeight));
5289             memset(cPath, 0, sizeof(cPath));
5290             last_weight = 1000;
5291             i = 0;
5292             while (hp[i] != NULL)
5293             {
5294                 if (sscanf(hp[i], "%*s %s", cPath))
5295                 {
5296                     if (strnicmp(cPath, AFS, strlen(AFS)) == 0)
5297                     {
5298                         if (sscanf(hp[i], "%*s %*s %*s %*s %s", cWeight))
5299                         {
5300                             if (atoi(cWeight) < last_weight)
5301                             {
5302                                 strcpy(path, cPath);
5303                                 last_weight = (int)atoi(cWeight);
5304                             }
5305                         }
5306                         else 
5307                             strcpy(path, cPath);
5308                     }
5309                 }
5310               ++i;
5311             }
5312             if (strlen(path))
5313             {
5314                 if (!strnicmp(path, AFS, strlen(AFS)))
5315                 {
5316                     AfsToWinAfs(path, winPath);
5317                     strcpy(winProfile, winPath);
5318                     strcat(winProfile, "\\.winprofile");
5319                 }
5320             }
5321         }
5322         else
5323             return(n);
5324     }
5325
5326     if ((!strcasecmp(WinHomeDir, "[dfs]")) || (!strcasecmp(WinProfileDir, "[dfs]")))
5327     {
5328         sprintf(path, "\\\\%s\\dfs\\profiles\\%c\\%s", ldap_domain, user_name[0], user_name);
5329         if (!strcasecmp(WinProfileDir, "[dfs]"))
5330           {
5331             strcpy(winProfile, path);
5332             strcat(winProfile, "\\.winprofile");
5333           }
5334         if (!strcasecmp(WinHomeDir, "[dfs]"))
5335           strcpy(winPath, path);
5336     }
5337
5338     if (hp != NULL)
5339     {
5340         i = 0;
5341         while (hp[i])
5342         {
5343             free(hp[i]);
5344             i++;
5345         }
5346     }
5347
5348     if (!strcasecmp(WinHomeDir, "[local]"))
5349         memset(winPath, '\0', sizeof(winPath));
5350     else if (!strcasecmp(WinHomeDir, "[afs]") || !strcasecmp(WinHomeDir, "[dfs]"))
5351     {
5352         strcpy(homeDrive, "H:");
5353     }
5354     else
5355     {
5356         strcpy(winPath, WinHomeDir);
5357         if (!strncmp(WinHomeDir, "\\\\", 2))
5358         {
5359             strcpy(homeDrive, "H:");
5360         }        
5361     }
5362
5363     // nothing needs to be done if WinProfileDir is [afs].
5364     if (!strcasecmp(WinProfileDir, "[local]"))
5365         memset(winProfile, '\0', sizeof(winProfile));
5366     else if (strcasecmp(WinProfileDir, "[afs]") && strcasecmp(WinProfileDir, "[dfs]"))
5367     {
5368         strcpy(winProfile, WinProfileDir);
5369     }
5370
5371     if (strlen(winProfile) != 0)
5372     {
5373         if (winProfile[strlen(winProfile) - 1] == '\\')
5374             winProfile[strlen(winProfile) - 1] = '\0';
5375     }
5376     if (strlen(winPath) != 0)
5377     {
5378         if (winPath[strlen(winPath) - 1] == '\\')
5379             winPath[strlen(winPath) - 1] = '\0';
5380     }
5381
5382     if ((winProfile[1] == ':') && (strlen(winProfile) == 2))
5383         strcat(winProfile, "\\");
5384     if ((winPath[1] == ':') && (strlen(winPath) == 2))
5385         strcat(winPath, "\\");
5386
5387     if (strlen(winPath) == 0)
5388     {
5389         if (OpType == LDAP_MOD_REPLACE)
5390         {
5391             i = 0;
5392             DEL_ATTR("homeDirectory", LDAP_MOD_DELETE);
5393             DelMods[i] = NULL;
5394             //unset homeDirectory attribute for user.
5395             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
5396             free(DelMods[0]);
5397         }
5398     }
5399     else
5400     {
5401         homedir_v[0] = strdup(winPath);
5402         ADD_ATTR("homeDirectory", homedir_v, OpType);
5403     }
5404
5405     if (strlen(winProfile) == 0)
5406     {
5407         if (OpType == LDAP_MOD_REPLACE)
5408         {
5409             i = 0;
5410             DEL_ATTR("profilePath", LDAP_MOD_DELETE);
5411             DelMods[i] = NULL;
5412             //unset profilePate attribute for user.
5413             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
5414             free(DelMods[0]);
5415         }
5416     }
5417     else
5418     {
5419         winProfile_v[0] = strdup(winProfile);
5420         ADD_ATTR("profilePath", winProfile_v, OpType);
5421     }
5422
5423     if (strlen(homeDrive) == 0)
5424     {
5425         if (OpType == LDAP_MOD_REPLACE)
5426         {
5427             i = 0;
5428             DEL_ATTR("homeDrive", LDAP_MOD_DELETE);
5429             DelMods[i] = NULL;
5430             //unset homeDrive attribute for user
5431             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
5432             free(DelMods[0]);
5433         }
5434     }
5435     else
5436     {
5437         drives_v[0] = strdup(homeDrive);
5438         ADD_ATTR("homeDrive", drives_v, OpType);
5439     }
5440
5441     return(n);
5442 }
5443
5444 int GetServerList(char *ldap_domain, char **ServerList)
5445 {
5446   unsigned long   rc;
5447   int             group_count;
5448   int             UseSFU30;
5449   int             Count;
5450   int             i;
5451   int             k;
5452   int             ServerListFound;
5453   char            default_server[256];
5454   char            dn_path[256];
5455   char            *attr_array[3];
5456   char            *sPtr;
5457   char            base[128];
5458   char            filter[128];
5459   char            temp[128];
5460   LK_ENTRY        *group_base;
5461   LK_ENTRY        *gPtr;
5462   LDAP            *ldap_handle;
5463   FILE            *fptr;
5464
5465   memset(default_server, '\0', sizeof(default_server));
5466   memset(dn_path, '\0', sizeof(dn_path));
5467   for (i = 0; i < MAX_SERVER_NAMES; i++)
5468     {
5469       if (ServerList[i] != NULL)
5470         {
5471           free(ServerList[i]);
5472           ServerList[i] = NULL;
5473         }
5474     }
5475   if (rc = ad_connect(&ldap_handle, ldap_domain, dn_path, "", "", default_server, 0, 
5476                       ServerList))
5477       return(1);
5478
5479   for (i = 0; i < MAX_SERVER_NAMES; i++)
5480     {
5481       ServerList[i] = NULL;
5482     }
5483
5484   memset(ServerList, '\0', sizeof(ServerList[0]) * MAX_SERVER_NAMES);
5485   group_count = 0;
5486   group_base = NULL;
5487   Count = 0;
5488   ServerListFound = 0;
5489
5490   strcpy(filter, "(&(objectClass=rIDManager)(fSMORoleOwner=*))");
5491   attr_array[0] = "fSMORoleOwner";
5492   attr_array[1] = NULL;
5493   if (!(rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
5494                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
5495     {
5496       if (group_count != 0)
5497         {
5498           sPtr = strstr(group_base->value, ",CN=");
5499           if (sPtr != NULL)
5500             {
5501               sPtr += strlen(",CN=");
5502               if (ServerList[0] == NULL)
5503                   ServerList[0] = calloc(1, 256);
5504               strcpy(ServerList[0], sPtr);
5505               sPtr = strstr(ServerList[0], ",");
5506               if (sPtr != NULL)
5507                   (*sPtr) = '\0';
5508               ++Count;
5509               ServerListFound = 1;
5510             }
5511         }
5512     }
5513   linklist_free(group_base);
5514
5515   group_count = 0;
5516   group_base = NULL;
5517   attr_array[0] = "cn";
5518   attr_array[1] = NULL;
5519   strcpy(filter, "(cn=*)");
5520   sprintf(base, "cn=Servers,cn=Default-First-Site-Name,cn=Sites,cn=Configuration,%s", dn_path);
5521
5522   if (!(rc = linklist_build(ldap_handle, base, filter, attr_array, 
5523                            &group_base, &group_count, LDAP_SCOPE_ONELEVEL)) != 0)
5524     {
5525       if (group_count != 0)
5526         {
5527           gPtr = group_base;
5528           while (gPtr != NULL)
5529             {
5530               if (ServerListFound != 0)
5531                 {
5532                   if (!strcasecmp(ServerList[0], gPtr->value))
5533                     {
5534                       gPtr = gPtr->next;
5535                       continue;
5536                     }
5537                 }
5538               if (Count < MAX_SERVER_NAMES)
5539                 {
5540                   if (ServerList[Count] == NULL)
5541                       ServerList[Count] = calloc(1, 256);
5542                   strcpy(ServerList[Count], gPtr->value);
5543                   gPtr = gPtr->next;
5544                   ++Count;
5545                 }
5546             }
5547         }
5548     }
5549   linklist_free(group_base);
5550
5551   UseSFU30 = 0;
5552   group_count = 0;
5553   group_base = NULL;
5554
5555   strcpy(filter, "(cn=msSFU-30-Uid-Number)");
5556   sprintf(base, "cn=schema,cn=configuration,%s", dn_path);
5557
5558   if (!(rc = linklist_build(ldap_handle, base, filter, NULL, 
5559                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
5560     {
5561       if (group_count != 0)
5562         {
5563           UseSFU30 = 1;
5564         }
5565     }
5566   linklist_free(group_base);
5567   group_count = 0;
5568   group_base = NULL;
5569
5570   sprintf(temp, "%s%s.cfg", CFG_PATH, ldap_domain);
5571   if ((fptr = fopen(temp, "w+")) != NULL)
5572     {
5573       fprintf(fptr, "%s %s\n", DOMAIN, ldap_domain);
5574       if (strlen(PrincipalName) != 0)
5575           fprintf(fptr, "%s %s\n", PRINCIPALNAME, PrincipalName);
5576       if (UseSFU30)
5577           fprintf(fptr, "%s %s\n", MSSFU, SFUTYPE);
5578       for (i = 0; i < MAX_SERVER_NAMES; i++)
5579         {
5580           if (ServerList[i] != NULL)
5581             {
5582               fprintf(fptr, "%s %s\n", SERVER, ServerList[i]);
5583             }
5584         }
5585       fclose(fptr);
5586     }
5587   ldap_unbind_s(ldap_handle);
5588
5589   for (i = 0; i < MAX_SERVER_NAMES; i++)
5590     {
5591       if (ServerList[i] != NULL)
5592         {
5593           if (ServerList[i][strlen(ServerList[i]) - 1] == '\n')
5594               ServerList[i][strlen(ServerList[i]) - 1] = '\0';
5595           strcat(ServerList[i], ".");
5596           strcat(ServerList[i], ldap_domain);
5597           for (k = 0; k < (int)strlen(ServerList[i]); k++)
5598               ServerList[i][k] = toupper(ServerList[i][k]);
5599         }
5600     }
5601
5602   return(0);
5603 }
5604
5605 int attribute_update(LDAP *ldap_handle, char *distinguished_name, 
5606                       char *attribute_value, char *attribute, char *user_name)
5607 {
5608   char      *mod_v[] = {NULL, NULL};
5609   LDAPMod   *DelMods[20];
5610   LDAPMod   *mods[20];
5611   int       n;
5612   int       i;
5613   int       rc;
5614
5615   if (strlen(attribute_value) == 0)
5616     {
5617       i = 0;
5618       DEL_ATTR(attribute, LDAP_MOD_DELETE);
5619       DelMods[i] = NULL;
5620       rc = ldap_modify_s(ldap_handle, distinguished_name, DelMods);
5621       free(DelMods[0]);
5622     }
5623     else
5624     {
5625       n = 0;
5626       mod_v[0] = attribute_value;
5627       ADD_ATTR(attribute, mod_v, LDAP_MOD_REPLACE);
5628       mods[n] = NULL;
5629       if ((rc = ldap_modify_s(ldap_handle, distinguished_name, mods)) != LDAP_SUCCESS)
5630         {
5631           free(mods[0]);
5632           n = 0;
5633           mod_v[0] = attribute_value;
5634           ADD_ATTR(attribute, mod_v, LDAP_MOD_ADD);
5635           mods[n] = NULL;
5636           if ((rc = ldap_modify_s(ldap_handle, distinguished_name, mods)) != LDAP_SUCCESS)
5637             {
5638               com_err(whoami, 0, "Unable to change the %s attribute for %s in the AD : %s",
5639                       attribute, user_name, ldap_err2string(rc));
5640             }
5641         }
5642       free(mods[0]);
5643     }
5644   return(rc);
5645 }
5646
5647 int tickets_get_k5()
5648 {
5649     char temp[128];
5650     char KinitPath[128];
5651     int  retval;
5652     int  i;
5653     static char EnvVar[128];
5654     static char EnvVar1[128];
5655
5656     strcpy(EnvVar, KRB5CCNAME);
5657     retval = putenv(EnvVar);
5658     strcpy(EnvVar1, KRBTKFILE);
5659     retval = putenv(EnvVar1);
5660
5661     for (i = 0; i < (int)strlen(PrincipalName); i++)
5662         PrincipalName[i] = tolower(PrincipalName[i]);
5663     if (strlen(PrincipalName) == 0)
5664     {
5665         strcpy(PrincipalName, PRODUCTION_PRINCIPAL);
5666         if (strcasecmp(ldap_domain, PRIMARY_DOMAIN))
5667             strcpy(PrincipalName, TEST_PRINCIPAL);
5668     }
5669
5670     memset(KinitPath, '\0',sizeof(KinitPath));
5671 #ifndef _WIN32
5672     strcpy(KinitPath, "/usr/athena/bin/");
5673 #endif
5674     sprintf(temp, "%skinit -k -t %s %s", KinitPath, KEYTABFILE, PrincipalName);
5675     retval = system(temp);
5676     if (retval)
5677       {
5678         com_err(whoami, 0, "%s failed", temp);
5679         sprintf(temp, "%skinit -5 -k -t %s %s", KinitPath, KEYTABFILE, PrincipalName);
5680         retval = system(temp);
5681         if (retval)
5682           {
5683             com_err(whoami, 0, "%s failed", temp);
5684             return(-1);
5685           }
5686       }
5687     return(0);
5688 }
5689
5690 int get_tickets()
5691 {
5692
5693     if (tickets_get_k5())
5694     {
5695         sleep(1);
5696         if (tickets_get_k5())
5697           {
5698             com_err(whoami, 0, "%s", "Unable to get kerberos tickets");
5699             critical_alert("AD incremental", "%s",
5700                            "winad.incr incremental failed (unable to get kerberos tickets)");
5701             return(1);
5702           }
5703     }
5704     return(0);
5705 }
5706
5707 int destroy_cache(void)
5708 {
5709   krb5_context          context;
5710   krb5_ccache                   cache;
5711   krb5_error_code       rc;
5712
5713   context = NULL;
5714   cache = NULL;
5715   if (!krb5_init_context(&context))
5716     {
5717       if (!krb5_cc_default(context, &cache))
5718         rc = krb5_cc_destroy(context, cache);
5719     }
5720   if (context != NULL)
5721     krb5_free_context(context);
5722   dest_tkt();
5723
5724   return(rc);
5725 }
5726
5727
5728 void StringTrim(char *StringToTrim)
5729 {
5730     char    *cPtr;
5731     char    temp[256];
5732     int     i;
5733
5734     if (strlen(StringToTrim) == 0)
5735         return;
5736
5737     cPtr = StringToTrim;
5738     while (isspace(*cPtr))
5739     {
5740         ++cPtr;
5741     }
5742     strcpy(temp, cPtr);
5743     if (strlen(temp) == 0)
5744     {
5745         strcpy(StringToTrim, temp);
5746         return;
5747     }
5748     while (1)
5749     {
5750         i = strlen(temp);
5751         if (i == 0)
5752             break;
5753         if (!isspace(temp[i-1]))
5754             break;
5755         temp[i-1] = '\0';
5756     }
5757
5758     strcpy(StringToTrim, temp);
5759     return;
5760 }
5761
5762 int ReadConfigFile(char *DomainName)
5763 {
5764     int     Count;
5765     int     i;
5766     int     k;
5767     char    temp[256];
5768     char    temp1[256];
5769     FILE    *fptr;
5770
5771     Count = 0;
5772
5773     sprintf(temp, "%s%s.cfg", CFG_PATH, DomainName);
5774     if ((fptr = fopen(temp, "r")) != NULL)
5775     {
5776         while (fgets(temp, sizeof(temp), fptr) != 0)
5777         {
5778             for (i = 0; i < (int)strlen(temp); i++)
5779                 temp[i] = toupper(temp[i]);
5780             if (temp[strlen(temp) - 1] == '\n')
5781                 temp[strlen(temp) - 1] = '\0';
5782             StringTrim(temp);
5783             if (strlen(temp) == 0)
5784                 continue;
5785             if (!strncmp(temp, DOMAIN, strlen(DOMAIN)))
5786             {
5787                 if (strlen(temp) > (strlen(DOMAIN)))
5788                 {
5789                     strcpy(ldap_domain, &temp[strlen(DOMAIN)]);
5790                     StringTrim(ldap_domain);
5791                 }
5792             }
5793             else if (!strncmp(temp, PRINCIPALNAME, strlen(PRINCIPALNAME)))
5794             {
5795                 if (strlen(temp) > (strlen(PRINCIPALNAME)))
5796                 {
5797                     strcpy(PrincipalName, &temp[strlen(PRINCIPALNAME)]);
5798                     StringTrim(PrincipalName);
5799                 }
5800             }
5801             else if (!strncmp(temp, SERVER, strlen(SERVER)))
5802             {
5803                 if (strlen(temp) > (strlen(SERVER)))
5804                 {
5805                     ServerList[Count] = calloc(1, 256);
5806                     strcpy(ServerList[Count], &temp[strlen(SERVER)]);
5807                     StringTrim(ServerList[Count]);
5808                     ++Count;
5809                 }
5810             }
5811             else if (!strncmp(temp, MSSFU, strlen(MSSFU)))
5812             {
5813                 if (strlen(temp) > (strlen(MSSFU)))
5814                 {
5815                     strcpy(temp1, &temp[strlen(MSSFU)]);
5816                     StringTrim(temp1);
5817                     if (!strcmp(temp1, SFUTYPE))
5818                         UseSFU30 = 1;
5819                 }
5820             }
5821             else if (!strcasecmp(temp, "NOCHANGE"))
5822             {
5823                 NoChangeConfigFile = 1;
5824             }
5825             else
5826             {
5827                 if (strlen(ldap_domain) != 0)
5828                 {
5829                     memset(ldap_domain, '\0', sizeof(ldap_domain));
5830                     break;
5831                 }
5832                 if (strlen(temp) != 0)
5833                     strcpy(ldap_domain, temp);
5834             }
5835         }
5836         fclose(fptr);
5837     }
5838
5839     if (strlen(ldap_domain) == 0)
5840     {
5841       strcpy(ldap_domain, DomainName);
5842     }
5843     if (Count == 0)
5844         return(0);
5845     for (i = 0; i < Count; i++)
5846     {
5847         if (ServerList[i] != 0)
5848         {
5849             strcat(ServerList[i], ".");
5850             strcat(ServerList[i], ldap_domain);
5851             for (k = 0; k < (int)strlen(ServerList[i]); k++)
5852                 ServerList[i][k] = toupper(ServerList[i][k]);
5853         }
5854     }
5855     return(0);
5856 }
5857
5858 int ReadDomainList()
5859 {
5860   int     Count;
5861   int     i;
5862   char    temp[128];
5863   char    temp1[128];
5864   FILE    *fptr;
5865   unsigned char c[11];
5866   unsigned char stuff[256];
5867   int     rc;
5868   int     ok;
5869
5870   Count = 0;
5871   sprintf(temp, "%s%s", CFG_PATH, WINADCFG);
5872   if ((fptr = fopen(temp, "r")) != NULL)
5873     {
5874       while (fgets(temp, sizeof(temp), fptr) != 0)
5875         {
5876           for (i = 0; i < (int)strlen(temp); i++)
5877             temp[i] = toupper(temp[i]);
5878           if (temp[strlen(temp) - 1] == '\n')
5879             temp[strlen(temp) - 1] = '\0';
5880           StringTrim(temp);
5881           if (strlen(temp) == 0)
5882             continue;
5883           if (!strncmp(temp, DOMAIN, strlen(DOMAIN)))
5884             {
5885               if (strlen(temp) > (strlen(DOMAIN)))
5886                 {
5887                   strcpy(temp1, &temp[strlen(DOMAIN)]);
5888                   StringTrim(temp1);
5889                   strcpy(temp, temp1);
5890                 }
5891             }
5892           ok = 1;
5893           rc = sscanf(temp, "%c%c%c%c%c.%c%c%c.%c%c%c%s", &c[0],
5894                       &c[1], &c[2], &c[3], &c[4], &c[5], &c[6],
5895                       &c[7], &c[8], &c[9], &c[10], stuff);
5896           if (rc != 11)
5897             {
5898               rc = sscanf(temp, "%c%c%c%c.%c%c%c.%c%c%c%s", &c[0],
5899                           &c[1], &c[2], &c[3], &c[4], &c[5], &c[6],
5900                           &c[7], &c[8], &c[9], stuff);
5901               if (rc != 10)
5902                 {
5903                   rc = sscanf(temp, "%c%c%%c.%c%c%c.%c%c%c%s", &c[0],
5904                               &c[1], &c[2], &c[3], &c[4], &c[5],
5905                               &c[6], &c[7], &c[8], stuff);
5906                   if (rc != 9)
5907                     {
5908                       UpdateDomainList = 1;
5909                       ok = 0;
5910                     }
5911                 }
5912             }
5913           if (ok)
5914              {
5915                strcpy(DomainNames[Count], temp);
5916                StringTrim(DomainNames[Count]);
5917                ++Count;
5918              }
5919         }
5920       fclose(fptr);
5921     }
5922   if (Count == 0)
5923     {
5924       critical_alert("incremental", "%s",
5925                      "winad.incr cannot run due to a configuration error in winad.cfg");
5926       return(1);
5927     }
5928   return(0);
5929 }
5930
5931 void WriteDomainList()
5932 {
5933   char    temp[128];
5934   int     i;
5935   FILE    *fptr;
5936   
5937   sprintf(temp, "%s%s", CFG_PATH, WINADCFG);
5938   if ((fptr = fopen(temp, "w+")) != NULL)
5939     {
5940       for (i = 0; i < MAX_DOMAINS; i++)
5941         {
5942           if (strlen(DomainNames[i]) != 0)
5943             {
5944               fprintf(fptr, "%s\n", DomainNames[i]);
5945             }
5946         }
5947       fclose(fptr);
5948     }
5949 }
This page took 7.05371 seconds and 3 git commands to generate.