1 /****^  ***********************************************************
  2         *                                                         *
  3         * Copyright, (C) Honeywell Bull Inc., 1987                *
  4         *                                                         *
  5         * Copyright, (C) Honeywell Information Systems Inc., 1982 *
  6         *                                                         *
  7         * Copyright (c) 1972 by Massachusetts Institute of        *
  8         * Technology and Honeywell Information Systems, Inc.      *
  9         *                                                         *
 10         *********************************************************** */
 11 
 12 
 13 /* format: style2 */
 14 retv_util:
 15      proc;
 16 
 17 /* This routine provides some utility functions for the volume retriever.  They consist of a
 18    check entry to determine if an object exists, a status entry to provide information about an
 19    object, a name list entry to return the primary names of all enties in a directory,  an interface to the
 20    system's hash routine to facilitate searching of a directory image recovered from a dump volume,
 21    an entry to set the bit count of an object recovered by the retriever,
 22    an entry to delete a branch recovered by the retriever,
 23    and an add names entry  and add acl entry which provide access control bypass for the retriever.
 24 */
 25 
 26 
 27 /* coded by Vinograd 9/76 */
 28 /* Modified 07/77 by THVV for bad_dir_ check */
 29 /* Added entry get_entry May 1978 by DRV */
 30 /* Added entry to set bit count March 1981 by DRV */
 31 /* Added entry to delete retrieved entry April 1981 by DRV */
 32 /* Use of SystemFreeSeg removed BIM 4/82. */
 33 /* Changed to use the new dc_find July 1984 by KPL */
 34 /* Changed to provide auditing info, November 1984 by KPL */
 35 
 36 /* Parameters */
 37 
 38           dcl     a_access_name          char (*);
 39           dcl     a_aclc                 fixed bin;
 40           dcl     a_aclp                 ptr;
 41           dcl     a_areap                ptr;
 42           dcl     a_auth                 bit (72) aligned;
 43           dcl     a_code                 fixed bin (35);
 44           dcl     a_dirname              char (*);
 45           dcl     a_dp                   ptr;
 46           dcl     a_dtd                  bit (36) aligned;
 47           dcl     a_dtm                  bit (36);
 48           dcl     a_ename                char (*);
 49           dcl     a_ep                   ptr;
 50           dcl     a_level                fixed bin;
 51           dcl     a_mode                 bit (36) aligned;
 52           dcl     a_new_bc               fixed bin (24);
 53           dcl     a_newname              char (*);
 54           dcl     a_nlc                  fixed bin;
 55           dcl     a_nlp                  ptr;
 56           dcl     a_np                   ptr;
 57           dcl     a_old_bc               fixed bin (24);
 58           dcl     a_pmode                bit (36) aligned;
 59           dcl     a_pvid                 bit (36) aligned;
 60           dcl     a_type                 fixed bin;
 61           dcl     a_uid                  bit (36) aligned;
 62           dcl     a_volid                (3) bit (36) aligned;
 63 
 64 /* Variables */
 65 
 66           dcl     DIRECTORY              fixed bin int static init (2) options (constant);
 67           dcl     LINK                   fixed bin int static init (3) options (constant);
 68           dcl     SEGMENT                fixed bin int static init (1) options (constant);
 69           dcl     check_entry            fixed bin static init (1) options (constant);
 70           dcl     delete_entry           fixed bin static init (5) options (constant);
 71           dcl     get_entry              fixed bin static init (3) options (constant);
 72           dcl     set_bc_entry           fixed bin static init (4) options (constant);
 73           dcl     status_entry           fixed bin static init (2) options (constant);
 74 
 75           dcl     access_name            char (32);
 76           dcl     acl_start_ptr          ptr;
 77           dcl     aclc                   fixed bin;
 78           dcl     aclp                   ptr;
 79           dcl     add_sw                 bit (1);
 80           dcl     auth                   bit (72);
 81           dcl     bmode                  bit (36) aligned;
 82           dcl     code                   fixed bin (35);
 83           dcl     dirl                   bit (1) aligned;
 84           dcl     dirname                char (168);
 85           dcl     dtd                    bit (36) aligned;
 86           dcl     dtm                    bit (36);
 87           dcl     ename                  char (32);
 88           dcl     entry_sw               fixed bin;
 89           dcl     exmode                 bit (36) aligned;
 90           dcl     i                      fixed bin;
 91           dcl     idx                    fixed bin;
 92           dcl     ignore                 fixed bin (35);
 93           dcl     level                  fixed bin;
 94           dcl     1 local_entry          like entry;
 95           dcl     1 local_vtoce          like vtoce aligned;
 96           dcl     mode                   bit (36) aligned;
 97           dcl     new_bc                 fixed bin (24);
 98           dcl     newname                char (32);
 99           dcl     nlc                    fixed bin;
100           dcl     nlp                    ptr;
101           dcl     old_bc                 fixed bin (24);
102           dcl     par_dirl               bit (1) aligned;
103           dcl     par_ep                 ptr;
104           dcl     pmode                  bit (36) aligned;
105           dcl     prior_dir_acl_count    fixed bin;
106           dcl     pvid                   bit (36) aligned;
107           dcl     pvtx                   fixed bin;
108           dcl     rp                     bit (18) aligned;
109           dcl     saved_change_pclock    fixed bin (35);
110           dcl     type                   fixed bin;
111           dcl     uid                    bit (36) aligned;
112           dcl     volid                  (3) bit (36) aligned;
113 
114 /* Based */
115 
116           dcl     1 acl_list             (aclc) aligned like input_acl based;
117           dcl     1 based_entry          like entry based (a_ep);
118           dcl     1 input_acl            based aligned,
119                     2 person             char (32),
120                     2 project            char (32),
121                     2 tag                char (1),
122                     2 mode               bit (36),
123                     2 exmode             bit (36);
124           dcl     name_list              (nlc) char (32) based aligned;
125           dcl     user_area              area based (a_areap);
126 
127 /* External */
128 
129           dcl     error_table_$vtoce_connection_fail
130                                          ext fixed bin (35);
131 
132 /* Entries */
133 
134           dcl     access_mode$user_effmode
135                                          entry (ptr, char (32), bit (72), fixed bin, bit (36) aligned, bit (36) aligned,
136                                          fixed bin (35));
137           dcl     acl_$add_entry         entry (fixed bin, bit (36) aligned, ptr, ptr, bit (1), fixed bin (35));
138           dcl     acl_$del_acl           entry (ptr, fixed bin (35));
139           dcl     chname$retv            entry (ptr, char (*), char (*), fixed bin (35));
140           dcl     delentry$salv_delete_branch
141                                          entry (ptr, fixed bin (35));
142           dcl     get_pvtx               entry (bit (36), fixed bin (35)) returns (fixed bin);
143           dcl     getuid                 entry returns (bit (36));
144           dcl     hash$search            entry (ptr, ptr, ptr, fixed bin (35));
145           dcl     lock$dir_lock_read     entry (ptr, fixed bin (35));
146           dcl     lock$dir_unlock        entry (ptr);
147           dcl     sum$dirmod             entry (pointer);
148           dcl     sum$getbranch          entry (ptr, fixed bin, ptr, fixed bin (35));
149           dcl     vtoc_man$get_vtoce     entry (bit (36), fixed bin, fixed bin, bit (3), ptr, fixed bin (35));
150 
151 /* Misc */
152 
153           dcl     bad_dir_               condition;
154           dcl     seg_fault_error        condition;
155 
156           dcl     addr                   builtin;
157           dcl     fixed                  builtin;
158           dcl     null                   builtin;
159           dcl     ptr                    builtin;
160           dcl     unspec                 builtin;
161 %page;
162 delete:
163      entry (a_dirname, a_ename, a_code);
164           entry_sw = delete_entry;
165           goto common;
166 
167 set_bc:
168      entry (a_dirname, a_ename, a_new_bc, a_old_bc, a_code);
169           entry_sw = set_bc_entry;
170           new_bc = a_new_bc;
171           goto common;
172 
173 get:
174      entry (a_dirname, a_ename, a_ep, a_code);
175           entry_sw = get_entry;
176           goto common;
177 
178 check:
179      entry (a_dirname, a_ename, a_type, a_dtm, a_code);
180 
181 /* set control arg and default return value */
182 
183           entry_sw = check_entry;
184           dtm = "0"b;
185           goto common;
186 
187 status:
188      entry (a_dirname, a_ename, a_auth, a_access_name, a_level, a_type, a_mode, a_pmode, a_uid, a_pvid, a_volid, a_dtd,
189           a_code);
190 
191 
192 /* set control arg, copy args */
193           entry_sw = status_entry;
194           access_name = a_access_name;
195           level = a_level;
196           auth = a_auth;
197 
198 /* set default return values */
199           uid = "0"b;
200           pvid = "0"b;
201           volid (*) = "0"b;
202           dtd = "0"b;
203           bmode = "0"b;
204           pmode = "0"b;
205 
206 common:                                                     /* copy args */
207           dirname = a_dirname;
208           ename = a_ename;
209 
210 /* set return valuse and control args */
211           code = 0;
212           type = 0;
213           dp = null;
214           dirl = "0"b;
215           par_dirl = "0"b;
216 
217 /* in the retriever's environment nothing can be trusted so be prepared */
218 
219           on seg_fault_error
220                begin;
221                     code = error_table_$vtoce_connection_fail;
222                     goto status_ret;
223                end;
224 
225 
226 /* locate entry desired */
227 
228           if entry_sw = delete_entry
229           then call dc_find$obj_delete_priv (dirname, ename, DC_FIND_NO_CHASE, ep, code);
230           else if entry_sw = set_bc_entry
231           then call dc_find$obj_status_write_priv (dirname, ename, DC_FIND_NO_CHASE, FS_OBJ_BC_MOD, ep, code);
232           else call dc_find$obj_status_read_priv (dirname, ename, DC_FIND_NO_CHASE, ep, code);
233           if code ^= 0
234           then goto status_ret;
235           dp = ptr (ep, 0);
236           dirl = "1"b;
237           if entry_sw = delete_entry
238           then do;
239                     call delentry$salv_delete_branch (ep, code);
240                     goto status_ret;
241                end;
242           if entry_sw = get_entry
243           then do;
244                     unspec (local_entry) = unspec (entry);
245                     goto status_ret;
246                end;
247           if entry_sw = set_bc_entry
248           then do;
249                     old_bc = entry.bc;
250                     entry.bc = new_bc;
251                     goto status_ret;
252                end;
253 
254 /* determine type */
255           if ^entry.bs
256           then type = LINK;
257           else if entry.dirsw
258           then type = DIRECTORY;
259           else type = SEGMENT;                              /* if status entry determine user access */
260           if entry_sw = status_entry
261           then do;
262                     uid = entry.uid;
263                     if type ^= LINK
264                     then do;
265                               pvid = entry.pvid;
266                               call access_mode$user_effmode (ep, access_name, auth, level, mode, exmode, code);
267                               if code ^= 0
268                               then goto status_ret;
269                               if entry.dirsw
270                               then bmode = exmode;
271                               else bmode = mode;
272                          end;
273                     call sum$getbranch (dp, 0, par_ep, code);
274                     if code ^= 0
275                     then goto status_ret;
276                     par_dirl = "1"b;
277 
278                     call access_mode$user_effmode (par_ep, access_name, auth, level, mode, exmode, code);
279                     if code ^= 0
280                     then goto status_ret;
281                     pmode = exmode;
282                end;                                         /* if branch then check if object it describes exists */
283 
284           if entry.bs
285           then do;
286                     unspec (local_vtoce) = "0"b;
287                     vtocep = addr (local_vtoce);
288                     pvtx = get_pvtx (entry.pvid, code);
289                     if code ^= 0
290                     then goto status_ret;
291                     call vtoc_man$get_vtoce (entry.pvid, pvtx, fixed (entry.vtocx, 17), "101"b, vtocep, code);
292                     if code ^= 0
293                     then goto status_ret;
294                     if vtoce.uid ^= entry.uid | vtoce.damaged
295                     then do;
296                               code = error_table_$vtoce_connection_fail;
297                               goto status_ret;
298                          end;
299                     if entry_sw = status_entry
300                     then do;
301                               volid (*) = vtoce.volid (*);
302                               dtd = vtoce.dtd;
303                          end;
304                     else dtm = vtoce.dtm;
305                end;
306 
307 /* clean up any locks and return values found */
308 status_ret:
309           if dp ^= null
310           then call dc_find$finished (dp, dirl);
311           if par_dirl
312           then call lock$dir_unlock (ptr (par_ep, 0));
313           if entry_sw = status_entry
314           then do;
315                     a_mode = bmode;
316                     a_pmode = pmode;
317                     a_uid = uid;
318                     a_pvid = pvid;
319                     a_volid (*) = volid (*);
320                     a_dtd = dtd;
321                     a_type = type;
322                end;
323           else if entry_sw = set_bc_entry
324           then do;
325                     a_old_bc = old_bc;
326                end;
327           else if entry_sw = check_entry
328           then do;
329                     a_dtm = dtm;
330                     a_type = type;
331                end;
332           else if entry_sw = get_entry
333           then do;
334                     local_entry.uid = getuid ();
335                     unspec (based_entry) = unspec (local_entry);
336                end;
337           a_code = code;
338           return;
339 %page;
340 name_list:
341      entry (a_dirname, a_areap, a_nlp, a_nlc, a_code);
342 
343 /* copy arg and set control args */
344           dirname = a_dirname;
345           code = 0;
346           dirl = "0"b;
347           idx = 0;
348           dp = null;
349 
350 /* find and lock dir */
351 
352 RETRY:    call dc_find$dir_read_priv (dirname, dp, code);
353           if code ^= 0
354           then goto name_list_ret;
355           dirl = "1"b;
356 
357           nlc = dir.seg_count + dir.dir_count + dir.lcount; /* number of primary names */
358           saved_change_pclock = dir.change_pclock;
359 
360           call lock$dir_unlock (dp);
361           dirl = "0"b;
362 
363 /* Unlock dir for allocate */
364 
365           allocate name_list in (user_area) set (nlp);
366 
367 /* Relock */
368 
369           call lock$dir_lock_read (dp, code);
370           if code ^= 0
371           then goto name_list_ret;
372           dirl = "1"b;
373 
374           if dir.change_pclock ^= saved_change_pclock
375           then do;
376                     call lock$dir_unlock (dp);
377                     dirl = "0"b;
378                     free nlp -> name_list;
379                     go to RETRY;
380                end;
381 
382 /* Now we have someplace to put the data, but it is user storage */
383 /* If we fault, though, the worst we do is salvage the dir. */
384 /* This entry is only called by trusted processes. */
385 
386           i = 0;
387           do rp = dir.entryfrp repeat (entry.efrp) while (rp ^= "0"b);
388                i = i + 1;
389                if i > nlc
390                then signal bad_dir_;
391                ep = ptr (dp, rp);
392                if entry.bs
393                then if entry.owner ^= dir.uid | entry.type ^= SEG_TYPE & entry.type ^= DIR_TYPE
394                     then signal bad_dir_;
395                     else ;
396                else if link.owner ^= dir.uid | link.type ^= LINK_TYPE
397                then signal bad_dir_;
398                idx = idx + 1;
399                nlp -> name_list (idx) = ptr (ep, entry.name_frp) -> names.name;
400           end;                                              /* unlock dir */
401           call lock$dir_unlock (dp);
402           dirl = "0"b;
403 
404 /* Return pointer and count */
405 
406           a_nlc = nlc;
407           a_nlp = nlp;
408 
409 name_list_ret:                                              /* unlock, dereference as required */
410           if dp ^= null
411           then call dc_find$finished (dp, dirl);
412           a_code = code;
413           return;
414 
415 /* hash_index_ is now available in bound_sss_active_, and this should */
416 /* be deleted ! */
417 
418 hash_search:
419      entry (a_dp, a_np, a_ep, a_code);
420 
421           call hash$search (a_dp, a_np, a_ep, a_code);
422           return;
423 
424 addname:
425      entry (a_dirname, a_ename, a_newname, a_code);
426 
427 /* copy input args and set control vars */
428           dirl = "0"b;
429           dirname = a_dirname;
430           ename = a_ename;
431           newname = a_newname;
432           dp = null;
433 
434 /* locate entry */
435 
436           call dc_find$obj_status_write_priv (dirname, ename, DC_FIND_NO_CHASE, FS_OBJ_RENAME, ep, code);
437           if code ^= 0
438           then goto addname_ret;
439           dirl = "1"b;
440           dp = ptr (ep, 0);                                 /* add name to entry bypassing access checks */
441           call chname$retv (ep, "", newname, code);
442 
443 addname_ret:                                                /* clean up */
444           if dp ^= null
445           then call dc_find$finished (dp, dirl);
446           a_code = code;
447           return;
448 
449 /* lookout. This entry takes dir control acl's, not asd_ style */
450 /* user acl structures. !!!! */
451 
452 add_acl:
453      entry (a_dirname, a_ename, a_aclp, a_aclc, a_code);    /* copy input args and set control vars */
454           dirname = a_dirname;
455           ename = a_ename;
456           aclc = a_aclc;
457           aclp = a_aclp;
458           dirl = "0"b;
459           dp = null;
460 
461 /* We do not copy the input data. First, this is called by trusted */
462 /* system code. Second, the worst that we can do is crawl out. */
463 /* boundsfaults do not hold write locks. */
464 
465 /* locate entry */
466 
467           call dc_find$obj_access_write_priv (dirname, ename, DC_FIND_NO_CHASE, FS_OBJ_ACL_MOD, ep, code);
468           if code ^= 0
469           then goto add_acl_ret;
470           dirl = "1"b;
471           dp = ptr (ep, 0);
472 
473 /* Loop over each acl term to be added. If unable to add delete all terms added so far.
474    Reset acl counts for directory and entry. */
475 
476           prior_dir_acl_count = dir.acle_total;
477           acl_start_ptr = addr (entry.acl_frp);
478           do i = 1 to aclc while (code = 0);
479                call acl_$add_entry (fixed (entry.acle_count), entry.uid, acl_start_ptr, addr (aclp -> acl_list (i)),
480                     add_sw, code);
481                if code ^= 0
482                then do;
483                          call acl_$del_acl (acl_start_ptr, ignore);
484                          dir.acle_total = prior_dir_acl_count;
485                     end;
486                else if add_sw
487                then do;
488                          dir.acle_total = dir.acle_total + 1;
489                          entry.acle_count = entry.acle_count + 1;
490                     end;
491           end;
492           call sum$dirmod (dp);
493 add_acl_ret:                                                /* clean up and unlock */
494           if dp ^= null
495           then call dc_find$finished (dp, dirl);
496           a_code = code;
497           return;
498 %page;
499 %include dc_find_dcls;
500 %page;
501 %include dir_entry;
502 %page;
503 %include dir_header;
504 %page;
505 %include dir_name;
506 %page;
507 %include dir_link;
508 %page;
509 %include fs_obj_access_codes;
510 %page;
511 %include fs_types;
512 %page;
513 %include vtoce;
514      end retv_util;