|
|
1.1 root 1: /* add_alias.c - a mutilated add.c*/
2:
3: #ifndef lint
4: static char *rcsid = "$Header: /f/osi/others/quipu/uips/manage/RCS/add_alias.c,v 7.1 90/07/27 08:47:16 mrose Exp $";
5: #endif
6:
7: /*
8: * $Header: /f/osi/others/quipu/uips/manage/RCS/add_alias.c,v 7.1 90/07/27 08:47:16 mrose Exp $
9: *
10: *
11: * $Log: add_alias.c,v $
12: * Revision 7.1 90/07/27 08:47:16 mrose
13: * update
14: *
15: * Revision 7.0 90/06/26 14:52:31 mrose
16: * *** empty log message ***
17: *
18: */
19:
20: /*
21: * NOTICE
22: *
23: * Acquisition, use, and distribution of this module and related
24: * materials are subject to the restrictions of a license agreement.
25: * Consult the Preface in the User's Manual for the full terms of
26: * this agreement.
27: *
28: */
29:
30:
31: #include "quipu/util.h"
32: #include "quipu/dua.h"
33: #include "quipu/add.h"
34: #include "quipu/entry.h"
35: #include "quipu/compare.h"
36: #include "quipu/modify.h"
37:
38: #define ORG_PERSON "thornPerson & quipuObject"
39: /* this should probably go elsewhere !!! */
40:
41: extern DN dn;
42: #define OPT (!frompipe || rps -> ps_byteno == 0 ? opt : rps)
43: #define RPS (!frompipe || opt -> ps_byteno == 0 ? rps : opt)
44: extern char frompipe;
45: extern PS opt;
46: extern PS rps;
47: extern Entry current_entry;
48: static char new_draft;
49:
50: call_add_alias (argc, argv)
51: int argc;
52: char **argv;
53: {
54: DN oj_dn, aoj_dn ;
55: DN save_dn, dnptr, trail ;
56: DN moddn;
57: extern DN str2dn_aux() ;
58: extern DN sequence_dn() ;
59: Entry entry_ptr;
60: FILE *fd;
61: PS tmp ;
62: PS str_ps;
63: char str_buffer[1000];
64: char fname[128];
65: char alias = FALSE ;
66:
67: struct ds_addentry_arg add_arg;
68: struct DSError error;
69: struct DSError compare_error;
70: struct ds_compare_result compare_result;
71: struct ds_compare_arg compare_arg;
72: struct ds_modifyentry_arg mod_arg;
73: struct DSError mod_error;
74: struct entrymod *emnew ;
75:
76: AV_Sequence objClassAVS ;
77: AV_Sequence treeStrAVS ;
78: Attr_Sequence get_attributes();
79:
80: extern int parse_status;
81:
82: int draft_flag = 0;
83: char *home;
84: char objectname[80] ;
85: char aliasobjectname[160] ;
86: char *contact_compare[6] ;
87: char *contact_showentry[6] ;
88: char *contact_modify[1] ;
89:
90: contact_compare[0] = "compare" ;
91: contact_compare[1] = "";
92: contact_compare[2] = "-attribute";
93: contact_compare[4] = "-noprint";
94: contact_compare[5] = "-dontdereferencealias" ;
95: contact_showentry[0] = "showentry";
96: contact_showentry[1] = "-noshow" ;
97: contact_showentry[2] = "-all" ;
98: contact_showentry[3] = "-nokey" ;
99: contact_showentry[4] = "-dontdereferencealias";
100: contact_modify[0] = "modify" ;
101:
102: emnew = em_alloc() ;
103: contact_showentry[5] = (char *) malloc ((unsigned)strlen(argv[2])) ;
104: (void)strcpy(contact_showentry[5], argv[2]) ;
105:
106: contact_compare[3] = (char *) malloc ((unsigned)strlen("objectClass=alias.")) ;
107: (void)strcpy(contact_compare[3], "objectClass=alias") ;
108:
109: if (service_control (OPT, 6, contact_compare, &compare_arg.cma_common) == -1)
110: {
111: ps_print(OPT, "Problems with compare service control flags.\n") ;
112: return ;
113: }
114:
115: if (home = getenv ("HOME"))
116: (void) sprintf (fname, "%s/.dishdraft", home);
117: else
118: (void) strcpy (fname, "./.dishdraft");
119: new_draft = FALSE;
120:
121: if ((argc = service_control (OPT, argc, argv, &add_arg.ada_common)) == -1)
122: return ;
123: if (argc < 3)
124: {
125: ps_printf(OPT, "Not enough arguments.\n") ;
126: Usage (argv[0]) ;
127: return ;
128: }
129: (void)strcpy(objectname, argv[1]) ;
130: (void)strcpy(aliasobjectname, argv[2]) ;
131:
132: /* Turn a sequence number back into a DN */
133: if (*aliasobjectname >= '0' && *aliasobjectname <= '9')
134: {
135: /* First convert the number into a dn */
136: aoj_dn = dn_cpy(sequence_dn(atoi(aliasobjectname))) ;
137: }
138: else
139: {
140: if (*aliasobjectname == '.')
141: {
142: ps_print(OPT, "..@ gives me a headache. Ambiguous. Abort... \n") ;
143: return ;
144: }
145:
146: if (*aliasobjectname == '@')
147: {
148: aoj_dn = dn_cpy(str2dn(aliasobjectname + 1)) ;
149: }
150: else
151: {
152: /*aoj_dn = dn_cpy(dn) ;
153: *dn_append(aoj_dn, dn_cpy(str2dn(aliasobjectname))) ;
154: */
155: save_dn = str2dn_aux(aliasobjectname,&alias) ;
156: if (save_dn != NULLDN)
157: {
158: if (alias)
159: {
160: aoj_dn = dn_cpy(save_dn);
161: }
162: else
163: {
164: if (dn == NULLDN)
165: {
166: aoj_dn = dn_cpy(save_dn) ;
167: }
168: else
169: {
170: aoj_dn = dn_cpy(dn) ;
171: dn_append (aoj_dn,save_dn);
172: }
173: }
174: }
175: dn_free(save_dn) ;
176: }
177: }
178:
179: if (*objectname >= '0' && *objectname <= '9')
180: {
181: /* First convert the number into a dn */
182: oj_dn = dn_cpy(sequence_dn(atoi(objectname))) ;
183: }
184: else
185: {
186: if (*objectname == '.')
187: {
188: ps_print(OPT, "..@ gives me a headache. Ambiguous. Abort... \n") ;
189: return ;
190: }
191:
192: if (*objectname == '@')
193: {
194: oj_dn = dn_cpy(str2dn(objectname + 1)) ;
195: }
196: else
197: {
198: oj_dn = dn_cpy(dn) ;
199: dn_append(oj_dn, dn_cpy(str2dn(objectname))) ;
200: }
201: }
202:
203: save_dn = dn_cpy(dn) ;
204: dn_free(dn) ;
205: dn = dn_cpy(aoj_dn) ;
206: if (!test_move_dn())
207: {
208: ps_print(OPT, "Can't move to ") ;
209: dn_print(OPT, dn, EDBOUT) ;
210: ps_print(OPT, ".\nAborting.\n") ;
211: return ;
212: }
213: compare_arg.cma_object = aoj_dn;
214: if (get_ava (&compare_arg.cma_purported, "objectClass", "alias") != OK)
215: {
216: ps_print(OPT, "Oops, 'objectClass=alias' is a bad attribute!\n") ;
217: ps_print(OPT, "This is very bad...\n") ;
218: return ;
219: }
220:
221: if (rebind () != OK)
222: return ;
223:
224: while (ds_compare (&compare_arg, &compare_error, &compare_result) != DS_OK)
225: {
226: if (dish_error (OPT, &compare_error) == 0)
227: {
228: return ;
229: }
230: compare_arg.cma_object = compare_error.ERR_REFERRAL.DSE_ref_candidates->cr_name;
231: }
232:
233: if ( compare_result.cmr_matched == 1 ) /* if <AOJ> is an alias, abort. */
234: {
235: ps_printf(OPT, "Sorry, %s is an alias.\nAliasing to aliases is illegal.\n", aliasobjectname) ;
236: return ;
237: }
238:
239: /* Now we want to discover the objectClass of our object, and make
240: * sure that this will be OK when we add in the alias. (ie fitting
241: * in with the treeStructure.)
242: */
243:
244: /* stick the aliasobjectname into the cache so we can read
245: * bits of information from it.
246: */
247:
248: call_showentry(6, contact_showentry) ;
249: contact_showentry[5] = (char *) malloc ((unsigned)strlen(argv[2])) ;
250: (void)strcpy(contact_showentry[5], argv[2]) ;
251:
252: if (current_entry == NULLENTRY)
253: {
254: ps_print(OPT, "Can't read ") ;
255: dn_print(OPT, dn, EDBOUT) ;
256: ps_print(OPT, " for objectClass attribute. Aborting.\n") ;
257: return ;
258: }
259: else
260: {
261: /* Find the objectClass attribute to compare with the tree
262: * structure of the node we are going to dangle the alias
263: * from.
264: * While we are at it, find out how many seeAlso attributes
265: * are present, so we can decide whether we need to add
266: * the entire attribute or just another value.
267: */
268:
269: Attr_Sequence eptr ;
270: AttributeType a_t = AttrT_new("objectClass") ;
271: AttributeType a_t2 = AttrT_new("seeAlso") ;
272:
273: emnew->em_type = EM_ADDATTRIBUTE ;
274: for (eptr = current_entry->e_attributes; eptr != NULLATTR; eptr = eptr->attr_link)
275: {
276: if ( AttrT_cmp (eptr->attr_type, a_t) == 0 )
277: {
278: objClassAVS = avs_cpy(eptr->attr_value);
279: }
280: if ( AttrT_cmp (eptr->attr_type, a_t2) == 0 )
281: {
282: emnew->em_type = EM_ADDVALUES ;
283: }
284: }
285: }
286: if (objClassAVS == NULLAV)
287: {
288: ps_print(OPT, "We can't find Object Class.... Aborting.\n") ;
289: return ;
290: }
291: /* We should have got the ObjectClass now, so return to where we were
292: * and move up a level to grab the tree structure */
293:
294: dn_free(dn) ;
295: dn = dn_cpy(oj_dn) ;
296:
297: for (dnptr = dn; dnptr->dn_parent != NULLDN; dnptr = dnptr->dn_parent)
298: trail = dnptr;
299: dn_comp_free (dnptr);
300: trail->dn_parent = NULLDN;
301:
302: contact_showentry[1] = ( char *) malloc ((unsigned)strlen("-noshow") + 1) ;
303: (void)strcpy(contact_showentry[1], "-noshow") ;
304: contact_showentry[2] = ( char *) malloc ((unsigned)strlen("-all") + 1) ;
305: (void)strcpy(contact_showentry[2], "-all") ;
306: contact_showentry[3] = ( char *) malloc ((unsigned)strlen("-nokey") + 1) ;
307: (void)strcpy(contact_showentry[3], "-nokey") ;
308: contact_showentry[4] = ( char *) malloc ((unsigned)strlen("-dontdereferencealias") + 1) ;
309: (void)strcpy(contact_showentry[4], "-dontdereferencealias") ;
310:
311: call_showentry(5, contact_showentry) ;
312:
313: if (current_entry == NULLENTRY)
314: {
315: ps_print(OPT, "Can't read ") ;
316: dn_print(OPT, dn, EDBOUT) ;
317: ps_print(OPT, " for the treeStructure. Aborting.\n") ;
318: return ;
319: }
320: else
321: {
322: Attr_Sequence eptr ;
323: AttributeType a_t = AttrT_new("treeStructure") ;
324:
325: for (eptr = current_entry->e_attributes; eptr != NULLATTR; eptr = eptr->attr_link)
326: {
327: if ( AttrT_cmp (eptr->attr_type, a_t) == 0 )
328: {
329: treeStrAVS = avs_cpy (eptr->attr_value) ;
330: }
331: }
332: }
333:
334: if (treeStrAVS == NULLAV)
335: {
336: ps_print(OPT, "Tree Structure Missing in ") ;
337: dn_print(OPT, dn, EDBOUT) ;
338: ps_print(OPT, ".\nAssuming that the add will be valid.\n") ;
339: }
340: else
341: {
342: if (test_schema(treeStrAVS, objClassAVS) != OK)
343: {
344: ps_print(OPT, "Not allowed to add this alias here.\n") ;
345: ps_print(OPT, "It would break the directory schema to add this alias here.\n") ;
346: return ;
347: }
348: }
349:
350: /* This is where we have to start being rather careful, previously
351: * we have just being reading and checking, but now we start to add
352: * things in, changing in several places. Mistakes => inconsistencies
353: * ie BAD...
354: */
355:
356: /* If we reach here, we should have the appropriate arguments,
357: * one is the new object,
358: * the other is an existing non-alias-entry object.
359: * We now write the information to a draft file, and 'whongo'
360: * the alias into the database.
361: */
362:
363: /* open the draft file for writing... */
364:
365: if ((fd = fopen (fname, "w")) == (FILE *) NULL)
366: {
367: ps_printf (OPT, "Can't open draft entry %s\n", fname);
368: return ;
369: }
370:
371: (void)fprintf(fd, "aliasedObjectName= ") ;
372: if ( ((tmp = ps_alloc (std_open)) != NULLPS) &&
373: (std_setup (tmp, fd) != NOTOK) )
374: {
375: dn_print(tmp, aoj_dn, EDBOUT) ;
376: }
377: else
378: {
379: ps_print(OPT, "Unable to open appropriate ps. Aborting..\n") ;
380: return ;
381: }
382: (void)fprintf(fd, "\nobjectClass= quipuObject & alias & top\n") ;
383: (void) fclose(fd) ;
384:
385: if (move (objectname) != OK)
386: {
387: ps_printf (OPT,"Unknown option %s\n",objectname);
388: return ;
389: }
390:
391: /* now parse the files */
392: if ((fd = fopen (fname, "r")) == (FILE *) NULL) {
393: ps_printf (OPT, "Can't open draft entry %s\n", fname);
394: return ;
395: }
396: entry_ptr = get_default_entry (NULLENTRY);
397: entry_ptr->e_attributes = get_attributes (fd);
398: (void) fclose (fd);
399: if (parse_status != 0)
400: return ;
401:
402: add_arg.ada_object = dn;
403: for (moddn = dn ; moddn->dn_parent != NULLDN; moddn=moddn->dn_parent)
404: ;
405: entry_ptr->e_name = rdn_cpy (moddn->dn_rdn);
406: add_arg.ada_entry = entry_ptr->e_attributes;
407:
408: if (rebind () != OK) {
409: entry_free (entry_ptr);
410: return ;
411: }
412:
413: while (ds_addentry (&add_arg, &error) != DS_OK) {
414: if (dish_error (OPT, &error) == 0) {
415: entry_free (entry_ptr);
416: return ;
417: }
418: add_arg.ada_object = error.ERR_REFERRAL.DSE_ref_candidates->cr_name;
419: }
420: ps_print (RPS, "Added ");
421: dn_print (RPS, dn, EDBOUT);
422: ps_print (RPS, "\n");
423: entry_free (entry_ptr);
424: make_old (fname,draft_flag);
425:
426: /* Now we have to add a "seeAlso=<DN>" attribute to the <AOJ> */
427:
428: if (service_control(OPT, 1, contact_modify, &mod_arg.mea_common) == -1)
429: {
430: ps_printf(OPT, "Add_alias: Badly wrong. Service controls for modify in error...\n") ;
431: return ;
432: }
433:
434: dn_free(dn) ;
435: dn = dn_cpy(save_dn) ;
436: {
437: AV_Sequence new_avs = avs_comp_alloc() ;
438: AttributeValue new_AV = AttrV_alloc() ;
439:
440: if ((str_ps = ps_alloc(str_open)) == NULLPS)
441: {
442: ps_printf(OPT, "Ps alloc for your string failed.\n") ;
443: return ;
444: }
445: if (str_setup (str_ps, str_buffer, 998, 1) == NOTOK)
446: {
447: ps_printf (OPT, "str_setup: %s", ps_error (str_ps -> ps_errno));
448: ps_free (str_ps);
449: return ;
450: }
451: dn_print(str_ps, oj_dn, EDBOUT) ;
452: *str_ps->ps_ptr = 0 ;
453: ps_free(str_ps) ;
454:
455: new_AV = AttrV_cpy(str2AttrV(str_buffer, str2syntax("DN"))) ;
456: new_avs = avs_comp_new(AttrV_cpy(new_AV)) ;
457: emnew->em_what = as_comp_new(AttrT_new("seeAlso"), new_avs, NULLACL_INFO) ;
458: }
459: emnew->em_next = NULLMOD ;
460: mod_arg.mea_object = aoj_dn;
461: mod_arg.mea_changes = emnew ;
462:
463: if (rebind () != OK)
464: return ;
465:
466: /*
467: * If this operation is time-stamped, it may have expired while the user
468: * was editing the entry. Re-calculate the time-stamp. Modify is the only
469: * dish command where this needs to be done.
470: */
471:
472: if ((mod_arg.mea_common.ca_security != (struct security_parms *) 0)
473: && (mod_arg.mea_common.ca_security->sp_time != NULLCP))
474: {
475: char *new_version();
476:
477: free(mod_arg.mea_common.ca_security->sp_time);
478: mod_arg.mea_common.ca_security->sp_time = new_version();
479: }
480:
481: /* If security parameters are present, take this to mean that strong
482: * authentication is required. This disallows 'parms + no signature'
483: * (pointless) and 'signature + no parms' (security risk).
484: */
485: if (mod_arg.mea_common.ca_security != (struct security_parms *) 0)
486: {
487: int encode_DAS_ModifyEntryArgumentData();
488: struct signature *sign_operation();
489: mod_arg.mea_common.ca_sig =
490: sign_operation((caddr_t)&mod_arg,
491: encode_DAS_ModifyEntryArgumentData);
492: }
493:
494: while (ds_modifyentry (&mod_arg, &mod_error) != DS_OK)
495: {
496: if (dish_error (OPT, &mod_error) == 0)
497: {
498: ps_print(OPT, "Unable to modify ") ;
499: dn_print(OPT, aoj_dn, EDBOUT) ;
500: ps_print(OPT, "\n") ;
501: return ;
502: }
503: mod_arg.mea_object = mod_error.ERR_REFERRAL.DSE_ref_candidates->cr_name;
504: }
505: ps_print (RPS, "Modified ");
506: dn_print (RPS, aoj_dn, EDBOUT);
507: ps_print (RPS, "\n");
508: delete_cache (aoj_dn); /* re-cache when next read */
509:
510: dn_free(dn) ;
511: dn = dn_cpy(save_dn) ;
512: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.