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 access_mode: proc;                                          /* This computes any of three modes to a segment: */
 13                                                             /* raw, access_authorization factored, and effective
 14                                                                (authorization and ring bracket factored) */
 15 
 16 /* modified by Kobziar on 11-12-73 to skip CACLs */
 17 /* modification to original access_mode for the 3 entry version by Kobziar July 74 */
 18 /* modified by DRV 8/76  to add entry user_effmode */
 19 /* Modified by MJG 8/79  to fix root dir special case */
 20 /* Modified by Keith Loepere 10/84 to return non-extended modes for dirs for
 21    which the process is not on the ACL */
 22 
 23 
 24 /****^  HISTORY COMMENTS:
 25   1) change(87-01-16,Farley), approve(87-02-25,MCR7613),
 26      audit(87-03-03,Lippard), install(87-03-30,MR12.1-1018):
 27      Changed to make Initializer go through entry checks like everybody else
 28      when the entry is a directory.  This will stop the Initializer from
 29      thinking that it is ok to treat directories like segments in some
 30      respects.
 31                                                    END HISTORY COMMENTS */
 32 
 33 
 34 dcl (pds$processid,
 35      tc_data$initializer_id) ext fixed bin (35);
 36 
 37 dcl  pds$access_name aligned ext,
 38      pds$access_authorization bit (72) aligned ext;
 39 
 40 dcl  acc_name_$elements entry (ptr, ptr, fixed bin (35)),
 41      usage_values entry (fixed bin, fixed bin (71)),
 42      level$get entry returns (fixed bin),
 43     (read_allowed_, read_write_allowed_, write_allowed_) entry (bit (72) aligned, bit (72) aligned) returns (bit (1) aligned);
 44 
 45 dcl (addr, max, null, ptr, rel, fixed) builtin;
 46 dcl  bad_dir_ condition;
 47 
 48 dcl (a_ep,
 49      authp,
 50      np) ptr;
 51 
 52 dcl (a_auth,
 53      auth) bit (72) aligned;
 54 
 55 dcl 1 uname aligned,
 56     2 person char (32),
 57     2 project char (32),
 58     2 tag char (1) unaligned;
 59 
 60 dcl (cpu1,
 61      cpu2) fixed bin (71);
 62 
 63 dcl (a_code,
 64      code) fixed bin (35);
 65 
 66 dcl (esw,
 67      i,
 68      nacls,
 69      a_val,
 70      val,
 71      pf1,
 72      pf2) fixed bin;
 73 
 74 dcl  a_user_name char (32) aligned;
 75 
 76 dcl (a_exmode,
 77      exmode, mode,
 78      a_mode) bit (36) aligned;
 79 
 80 dcl (persrp,
 81      projrp) bit (18) aligned;
 82 
 83 dcl  sys_control bit (1) aligned;
 84 
 85 dcl 1 name aligned based,
 86     2 person char (32),
 87     2 project char (32),
 88     2 tag char (1) unaligned;
 89 
 90 dcl (raw init (0),
 91      authorization init (1),
 92      effective init (2)) fixed bin static;
 93 
 94 dcl  error_table_$obsolete_function ext fixed bin (35);
 95 
 96 dcl (active_hardcore_data$total_cpu_ac,
 97      active_hardcore_data$max_cpu_ac) ext fixed bin (71);
 98 
 99 dcl (active_hardcore_data$total_ac,
100      active_hardcore_data$total_pf_ac,
101      active_hardcore_data$pf_long_ac,
102      active_hardcore_data$nacls_long_ac,
103      active_hardcore_data$max_pf_ac,
104      active_hardcore_data$max_acls_ac,
105      active_hardcore_data$acls_ac (13)) ext fixed bin;
106 
107           % include fs_types;
108           % include aim_template;
109           % include dir_header;
110           % include dir_entry;
111           % include dir_acl;
112 
113 /* ^L */
114 raw:      entry (a_ep, a_mode, a_exmode, a_code);           /* want raw mode */
115           esw = raw;
116           go to initializer_check;
117 
118 authorization: entry (a_ep, a_mode, a_exmode, a_code);      /* factor in access_authorization */
119           esw = authorization;
120           go to initializer_check;
121 
122 effective: entry (a_ep, a_mode, a_exmode, a_code);          /* factor ring brackets also */
123           esw = effective;
124           val = level$get ();
125                                                             /* initializer_check next */
126 initializer_check:
127           if pds$processid = tc_data$initializer_id then sys_control = "1"b; /* this is the initializer process */
128           else sys_control = "0"b;                          /* not the initializer */
129 
130           np = addr (pds$access_name);                      /* get ptr to name */
131 
132           if esw ^= raw then do;
133                authp = addr (auth);
134                auth = pds$access_authorization;
135           end;
136           go to common;
137 
138 user_effmode: entry (a_ep, a_user_name, a_auth, a_val, a_mode, a_exmode, a_code);
139 
140           val = a_val;
141           auth = a_auth;
142           authp = addr (auth);
143           esw = effective;
144           goto split_user_name;
145 
146 user:     entry (a_ep, a_user_name, a_mode, a_exmode, a_code); /* entry to compute mode for another user */
147 
148           esw = raw;                                        /* skip authorization checks, as caller is responsible for this */
149 
150 split_user_name:
151           sys_control = "0"b;                               /* don't allow access to be calculated for system control */
152           np = addr (uname);                                /* get ptr to name */
153           call acc_name_$elements (addr (a_user_name), np, code); /* break up user name into 3 part access name */
154           if code ^= 0 then go to invalid_name;
155 
156 
157 common:   ep = a_ep;
158           code = 0;                                         /* clear error code */
159 
160           if rel (ep) = "0"b then do;                       /* no more cacls */
161                code = error_table_$obsolete_function;
162                a_mode, a_exmode = "0"b;
163                goto st_ret;
164           end;
165 
166           if ep = null then do;                             /* special case the root */
167                if sys_control then a_exmode = "111"b;       /* if initializer calling on its own behalf */
168                                                             /* give it SMA access to the root */
169                else a_exmode = "100"b;                      /* give everyone S access to the root */
170                if esw = effective then do;                  /* if we must factor ring brackets */
171                     if val = 0 then                         /* Ring 0, */
172                          a_mode = "101"b;                   /*  give RW access */
173                     else a_mode = "000"b;                   /* otherwise, no access at all */
174                end;
175                else a_mode = "101"b;                        /* raw check, say RW */
176                goto st_ret;
177           end;
178 
179 
180           call usage_values (pf1, cpu1);                    /* start metering time */
181 
182           nacls = 0;                                        /* set number of acl entries examined to zero */
183 
184           if sys_control & entry.dirsw then do;             /* give initializer access to all directories */
185                mode = "101"b;
186                exmode = "111"b;
187                goto entry_check;
188           end;
189 
190 
191           i = 0;
192           do aclep = ptr (ep, entry.acl_frp) repeat ptr (ep, acl_entry.frp) while (rel (aclep));
193                i = i + 1;
194                if i > entry.acle_count
195                | acl_entry.owner ^= entry.uid
196                | acl_entry.type ^= ACLE_TYPE then signal bad_dir_;
197                nacls = nacls + 1;                           /* count number of ACL entries examined */
198                persrp = acl_entry.name.pers_rp;             /* get rp to person name */
199                if persrp ^= "0"b then do;                   /* if person name ^= "*" */
200                     if ptr (ep, persrp) -> access_name.name ^= np -> name.person then go to skip;
201                end;
202 
203                projrp = acl_entry.name.proj_rp;             /* get rp to project name */
204                if projrp ^= "0"b then do;                   /* if project ^= "*" */
205                     if ptr (ep, projrp) -> access_name.name ^= np -> name.project then go to skip;
206                end;
207 
208                if acl_entry.name.tag ^= "*" then            /* compare tags */
209                     if np -> name.tag ^= "*" then           /* allow access name to contain tag of "*" */
210                          if acl_entry.name.tag ^= np -> name.tag then
211                               go to skip;
212 
213                mode = acl_entry.mode;                       /* names match - return mode */
214                exmode = acl_entry.ex_mode;                  /* and extended mode */
215                go to entry_check;                           /* see if finished */
216 
217 skip:     end;
218 
219           if entry.dirsw then do;                           /* not on ACL but everyone can read dirs */
220                mode = "101"b;
221                exmode = "0"b;
222                go to entry_check;
223           end;
224 
225 err:
226           mode,                                             /* return null modes if no match */
227                exmode = "0"b;
228           go to meter;                                      /* gather numbers */
229 
230 entry_check:
231           if esw = raw then go to meter;
232 
233           if entry.dirsw then do;                           /* see what access left */
234                if authp -> aim_template.privileges.dir then go to factor_rb;
235                if (exmode & "011"b) = "000"b then go to check_read; /* if cannot modify or append
236                                                                * then skip read/write check */
237           end;
238 
239           else do;                                          /* a segment */
240                if authp -> aim_template.privileges.seg then go to factor_rb;
241                if (mode & "001"b) = "000"b then go to check_read; /* if cannot write, skip read-write check */
242                                                             /* w only mode must also clear security read-write check */
243           end;
244 
245           if read_write_allowed_ (auth, entry.access_class) then go to factor_rb;
246 
247 check_read:
248           if read_allowed_ (auth, entry.access_class) then do;
249                if entry.dirsw then exmode = exmode & "100"b;
250                else mode = mode & "110"b;                   /* must zero w because previous test could have failed */
251                go to factor_rb;
252           end;
253 
254 /* write up only on special system segments */
255           if ^entry.dirsw then
256                if entry.multiple_class then                 /* system segment */
257                     if fixed (entry.ring_brackets (3), 3) <= 1 then /* only valid if in security permiter */
258                          if write_allowed_ (auth, entry.access_class) then go to factor_rb;
259                                                             /* allow full access */
260 
261           go to err;                                        /* otherwise return null access */
262 
263 factor_rb:
264           if esw = authorization then go to meter;          /* skip rb part */
265 
266           if entry.dirsw then do;
267                if val <= fixed (entry.ex_ring_brackets (1), 3) then go to seg_rb_check;
268                if val > fixed (entry.ex_ring_brackets (2), 3) then exmode = "0"b;
269                else exmode = exmode & "100"b;               /* s only  */
270           end;
271 seg_rb_check:                                               /* do this factoring in dir case also */
272           if val = fixed (entry.ring_brackets (1), 3) then go to meter;
273           if val < fixed (entry.ring_brackets (1), 3) then mode = mode & "101"b;
274           else if val <= fixed (entry.ring_brackets (2), 3) then mode = mode & "110"b;
275           else if val <= fixed (entry.ring_brackets (3), 3) then mode = mode & "010"b;
276           else mode = "0"b;                                 /* return null */
277 
278 meter:                                                      /* update access computation statistics */
279           call usage_values (pf2, cpu2);
280           pf2 = pf2 - pf1;                                  /* get number of page faults */
281           cpu2 = cpu2 - cpu1;                               /* get cpu time */
282 
283           active_hardcore_data$total_ac =                   /* update total number of access computations */
284                active_hardcore_data$total_ac + 1;
285 
286           active_hardcore_data$total_pf_ac =                /* update total page faults taken in access computation */
287                active_hardcore_data$total_pf_ac + pf2;
288 
289           active_hardcore_data$total_cpu_ac =               /* update total cpu time */
290                active_hardcore_data$total_cpu_ac + cpu2;
291 
292           if active_hardcore_data$max_cpu_ac < cpu2 then do; /* update data on longest access computation */
293                active_hardcore_data$max_cpu_ac = cpu2;
294                active_hardcore_data$pf_long_ac = pf2;
295                active_hardcore_data$nacls_long_ac = nacls;  /* update number of acl entries searched */
296           end;
297 
298           if nacls > 15 then i = 13;                        /* calc index for histogram of number of acl entries */
299           else if nacls > 10 then i = 12;                   /* searched in an access computation */
300           else i = nacls + 1;
301           active_hardcore_data$acls_ac (i) =                /* update histogram */
302                active_hardcore_data$acls_ac (i) + 1;
303 
304           active_hardcore_data$max_pf_ac =                  /* update max page faults taken in access computation */
305                max (active_hardcore_data$max_pf_ac, pf2);
306 
307           active_hardcore_data$max_acls_ac =                /* update max number of acls searched */
308                max (active_hardcore_data$max_acls_ac, nacls);
309 
310 return:
311           a_mode = mode;
312           a_exmode = exmode;
313 st_ret:
314           a_code = code;
315           return;
316 
317 invalid_name:
318           a_mode, a_exmode = "0"b;                          /* you loose */
319           go to st_ret;
320 
321      end access_mode;