stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 1 | #!/bin/sh |
| 2 | # |
| 3 | # CDDL HEADER START |
| 4 | # |
| 5 | # The contents of this file are subject to the terms of the |
casper | aebb1c9 | 2006-02-21 00:59:39 -0800 | [diff] [blame] | 6 | # Common Development and Distribution License (the "License"). |
| 7 | # You may not use this file except in compliance with the License. |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 8 | # |
| 9 | # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
| 10 | # or http://www.opensolaris.org/os/licensing. |
| 11 | # See the License for the specific language governing permissions |
| 12 | # and limitations under the License. |
| 13 | # |
| 14 | # When distributing Covered Code, include this CDDL HEADER in each |
| 15 | # file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
| 16 | # If applicable, add the following below this CDDL HEADER, with the |
| 17 | # fields enclosed by brackets "[]" replaced with your own identifying |
| 18 | # information: Portions Copyright [yyyy] [name of copyright owner] |
| 19 | # |
| 20 | # CDDL HEADER END |
| 21 | # |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 22 | # i.rbac |
| 23 | # |
Nathan Bush | 1099afd | 2010-06-24 15:03:22 -0700 | [diff] [blame] | 24 | # Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 25 | # |
| 26 | # class action script for "rbac" class files |
| 27 | # installed by pkgadd |
| 28 | # |
| 29 | # Files in "rbac" class: |
| 30 | # |
Casper H.S. Dik | 06d0f3f | 2009-06-19 17:45:11 +0200 | [diff] [blame] | 31 | # /etc/security/{prof_attr,exec_attr,auth_attr} |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 32 | # /etc/user_attr |
| 33 | # |
| 34 | # Allowable exit codes |
| 35 | # |
| 36 | # 0 - success |
| 37 | # 2 - warning or possible error condition. Installation continues. A warning |
casper | aebb1c9 | 2006-02-21 00:59:39 -0800 | [diff] [blame] | 38 | # message is displayed at the time of completion. |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 39 | # |
| 40 | |
Casper H.S. Dik | 58f7c25 | 2009-07-10 21:31:05 +0200 | [diff] [blame] | 41 | umask 022 |
| 42 | |
vp157776 | 7a3d041 | 2006-08-20 23:36:03 -0700 | [diff] [blame] | 43 | tmp_dir=${TMPDIR:-/tmp} |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 44 | |
ahrens | fa9e406 | 2005-10-31 11:33:35 -0800 | [diff] [blame] | 45 | PATH="/usr/bin:/usr/sbin:${PATH}" |
| 46 | export PATH |
| 47 | |
| 48 | basename_cmd=basename |
| 49 | cp_cmd=cp |
| 50 | egrep_cmd=egrep |
| 51 | mv_cmd=mv |
| 52 | nawk_cmd=nawk |
| 53 | rm_cmd=rm |
| 54 | sed_cmd=sed |
| 55 | sort_cmd=sort |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 56 | |
| 57 | # $1 is the type |
| 58 | # $2 is the "old/existing file" |
| 59 | # $3 is the "new (to be merged)" file |
| 60 | # $4 is the output file |
| 61 | # returns 0 on success |
| 62 | # returns 2 on failure if nawk fails with non-zero exit status |
| 63 | # |
| 64 | dbmerge() { |
| 65 | # |
Casper H.S. Dik | d778625 | 2009-03-04 23:17:53 +0100 | [diff] [blame] | 66 | # Remove the ident lines. |
| 67 | # |
| 68 | ${egrep_cmd} -v '^#[pragma ]*ident' $2 > $4.old 2>/dev/null |
| 69 | # |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 70 | # If the new file has a Sun copyright, remove the Sun copyright from the old |
| 71 | # file. |
| 72 | # |
| 73 | newcr=`${egrep_cmd} '^# Copyright.*Sun Microsystems, Inc.' $3 \ |
| 74 | 2>/dev/null` |
| 75 | if [ -n "${newcr}" ]; then |
| 76 | $sed_cmd -e '/^# Copyright.*Sun Microsystems, Inc./d' \ |
| 77 | -e '/^# All rights reserved./d' \ |
| 78 | -e '/^# Use is subject to license terms./d' \ |
Casper H.S. Dik | d778625 | 2009-03-04 23:17:53 +0100 | [diff] [blame] | 79 | $4.old > $4.$$ 2>/dev/null |
| 80 | $mv_cmd $4.$$ $4.old |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 81 | fi |
| 82 | # |
Nathan Bush | 29c3196 | 2010-08-12 14:07:03 -0700 | [diff] [blame] | 83 | # If the new file has an Oracle copyright, remove both the Sun and Oracle |
| 84 | # copyrights from the old file. |
| 85 | # |
| 86 | oracle_cr=`${egrep_cmd} '^# Copyright.*Oracle and/or its affiliates.' \ |
| 87 | $3 2>/dev/null` |
| 88 | if [ -n "${oracle_cr}" ]; then |
| 89 | $sed_cmd -e '/^# Copyright.*Sun Microsystems, Inc./d' \ |
| 90 | -e '/^# All rights reserved./d' \ |
| 91 | -e '/^# Use is subject to license terms./d' \ |
| 92 | -e '/^# Copyright.*Oracle and\/or its affiliates./d' \ |
| 93 | $4.old > $4.$$ 2>/dev/null |
| 94 | $mv_cmd $4.$$ $4.old |
| 95 | fi |
| 96 | # |
casper | aebb1c9 | 2006-02-21 00:59:39 -0800 | [diff] [blame] | 97 | # If the new file has the CDDL, remove it from the old file. |
| 98 | # |
| 99 | newcr=`${egrep_cmd} '^# CDDL HEADER START' $3 2>/dev/null` |
| 100 | if [ -n "${newcr}" ]; then |
| 101 | $sed_cmd -e '/^# CDDL HEADER START/,/^# CDDL HEADER END/d' \ |
| 102 | $4.old > $4.$$ 2>/dev/null |
| 103 | $mv_cmd $4.$$ $4.old |
| 104 | fi |
| 105 | # |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 106 | # Remove empty lines and multiple instances of these comments: |
| 107 | # |
| 108 | $sed_cmd -e '/^# \/etc\/security\/exec_attr/d' -e '/^#$/d' \ |
| 109 | -e '/^# execution attributes for profiles./d' \ |
| 110 | -e '/^# See exec_attr(4)/d' \ |
| 111 | -e '/^# \/etc\/user_attr/d' \ |
| 112 | -e '/^# user attributes. see user_attr(4)/d' \ |
| 113 | -e '/^# \/etc\/security\/prof_attr/d' \ |
| 114 | -e '/^# profiles attributes. see prof_attr(4)/d' \ |
| 115 | -e '/^# See prof_attr(4)/d' \ |
| 116 | -e '/^# \/etc\/security\/auth_attr/d' \ |
| 117 | -e '/^# authorizations. see auth_attr(4)/d' \ |
| 118 | -e '/^# authorization attributes. see auth_attr(4)/d' \ |
| 119 | $4.old > $4.$$ |
| 120 | $mv_cmd $4.$$ $4.old |
| 121 | # |
| 122 | # Retain old and new header comments. |
| 123 | # |
| 124 | $sed_cmd -n -e '/^[^#]/,$d' -e '/^##/,$d' -e p $4.old > $4 |
| 125 | $rm_cmd $4.old |
| 126 | $sed_cmd -n -e '/^[^#]/,$d' -e '/^##/,$d' -e p $3 >> $4 |
| 127 | # |
Nathan Bush | 29c3196 | 2010-08-12 14:07:03 -0700 | [diff] [blame] | 128 | # If the output file now has both Sun and Oracle copyrights, remove |
| 129 | # the Sun copyright. |
| 130 | # |
| 131 | sun_cr=`${egrep_cmd} '^# Copyright.*Sun Microsystems, Inc.' \ |
| 132 | $4 2>/dev/null` |
| 133 | oracle_cr=`${egrep_cmd} '^# Copyright.*Oracle and/or its affiliates.' \ |
| 134 | $4 2>/dev/null` |
| 135 | if [ -n "${sun_cr}" ] && [ -n "${oracle_cr}" ]; then |
| 136 | $sed_cmd -e '/^# Copyright.*Sun Microsystems, Inc./d' \ |
| 137 | -e '/^# All rights reserved./d' \ |
| 138 | -e '/^# Use is subject to license terms./d' \ |
| 139 | $4 > $4.$$ 2>/dev/null |
| 140 | $mv_cmd $4.$$ $4 |
| 141 | fi |
| 142 | # |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 143 | # Handle line continuations (trailing \) |
| 144 | # |
| 145 | $sed_cmd \ |
| 146 | -e '/\\$/{N;s/\\\n//;}' -e '/\\$/{N;s/\\\n//;}' \ |
| 147 | -e '/\\$/{N;s/\\\n//;}' -e '/\\$/{N;s/\\\n//;}' \ |
| 148 | -e '/\\$/{N;s/\\\n//;}' -e '/\\$/{N;s/\\\n//;}' \ |
| 149 | $2 > $4.old |
| 150 | $sed_cmd \ |
| 151 | -e '/\\$/{N;s/\\\n//;}' -e '/\\$/{N;s/\\\n//;}' \ |
| 152 | -e '/\\$/{N;s/\\\n//;}' -e '/\\$/{N;s/\\\n//;}' \ |
| 153 | -e '/\\$/{N;s/\\\n//;}' -e '/\\$/{N;s/\\\n//;}' \ |
| 154 | $3 > $4.new |
| 155 | # |
Nathan Bush | 8d0bff0 | 2010-08-12 14:07:03 -0700 | [diff] [blame] | 156 | # The nawk script below processes the old and new files using up to |
| 157 | # three passes. If the old file is empty, only the final pass over |
| 158 | # the new file is required. |
| 159 | # |
| 160 | if [ -s $4.old ]; then |
| 161 | nawk_pass1=$4.old |
| 162 | nawk_pass2=$4.new |
| 163 | nawk_pass3=$4.new |
| 164 | else |
| 165 | nawk_pass1= |
| 166 | nawk_pass2= |
| 167 | nawk_pass3=$4.new |
| 168 | fi |
| 169 | # |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 170 | #!/usr/bin/nawk -f |
| 171 | # |
Nathan Bush | 8d0bff0 | 2010-08-12 14:07:03 -0700 | [diff] [blame] | 172 | # dbmerge type=[auth|prof|user|exec] [ old-file new-file ] new-file |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 173 | # |
| 174 | # Merge two versions of an RBAC database file. The output |
| 175 | # consists of the lines from the new-file, while preserving |
Nathan Bush | 8d0bff0 | 2010-08-12 14:07:03 -0700 | [diff] [blame] | 176 | # user customizations in the old-file. |
| 177 | # |
| 178 | # Entries in the new-file replace corresponding entries in the |
| 179 | # old-file, except as follows: For exec_attr, all old entries |
| 180 | # for profiles contained in the new-file are discarded. For |
| 181 | # user_attr, the "root" entry from the old-file is retained, |
| 182 | # and new keywords from the new-file are merged into it. |
| 183 | # |
| 184 | # Records with the same key field(s) are merged, so that the |
| 185 | # keyword/value section of each output record contains the union |
| 186 | # of the keywords found in all input records with the same key |
| 187 | # field(s). For selected multi-value keywords [1] the values from |
| 188 | # the new-file are merged with retained values from the old-file. |
| 189 | # Otherwise, the value for each keyword is the final value found |
| 190 | # in the new-file, except for keywords in the user_attr entry for |
| 191 | # "root" where values from the old-file are always retained. |
| 192 | # |
| 193 | # [1] The following file type and keyword combinations are merged: |
| 194 | # prof_attr: auths, profiles, privs |
| 195 | # user_attr: auths, profiles, roles |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 196 | # |
| 197 | # The output is run through sort except for the comments |
| 198 | # which will appear first in the output. |
| 199 | # |
casper | aebb1c9 | 2006-02-21 00:59:39 -0800 | [diff] [blame] | 200 | # |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 201 | $nawk_cmd ' |
| 202 | |
Nathan Bush | 8d0bff0 | 2010-08-12 14:07:03 -0700 | [diff] [blame] | 203 | # This script may be invoked with up to three file names. Each file |
| 204 | # name corresponds to a separate processing pass. The passes are |
| 205 | # defined as follows: |
| 206 | # |
| 207 | # Pass 1: Read existing data. |
| 208 | # Data from the old-file is read into memory. |
| 209 | # |
| 210 | # Pass 2: Remove obsolete data. |
| 211 | # Discard any data from the old-file that is part of profiles that |
| 212 | # are also in the new-file. (As a special case, the user_attr entry |
| 213 | # for 'root' is always retained.) |
| 214 | # |
| 215 | # Pass 3: Merge new data. |
| 216 | # Data from the new-file is merged with the remaining old-file data. |
| 217 | # (As a special case, exec_attr entries are replaced, not merged.) |
| 218 | |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 219 | BEGIN { |
Nathan Bush | 8d0bff0 | 2010-08-12 14:07:03 -0700 | [diff] [blame] | 220 | # The variable 'pass' specifies which type of processing to perform. |
| 221 | # When processing only one file, skip passes 1 and 2. |
| 222 | if (ARGC == 3) |
| 223 | pass += 2; |
| 224 | |
| 225 | # The array 'keyword_behavior' specifies the special treatment of |
| 226 | # [type, keyword] combinations subject to value merging. |
| 227 | keyword_behavior["prof", "auths"] = "merge"; |
| 228 | keyword_behavior["prof", "profiles"] = "merge"; |
| 229 | keyword_behavior["prof", "privs"] = "merge"; |
| 230 | keyword_behavior["user", "auths"] = "merge"; |
| 231 | keyword_behavior["user", "profiles"] = "merge"; |
| 232 | keyword_behavior["user", "roles"] = "merge"; |
| 233 | |
casper | aebb1c9 | 2006-02-21 00:59:39 -0800 | [diff] [blame] | 234 | FS=":" |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 235 | } |
| 236 | |
Nathan Bush | 8d0bff0 | 2010-08-12 14:07:03 -0700 | [diff] [blame] | 237 | # When FNR (current file record number) is 1 it indicates that nawk |
| 238 | # is starting to read the next file specified on its command line, |
| 239 | # and is beginning the next processing pass. |
| 240 | FNR == 1 { |
| 241 | pass++; |
| 242 | } |
| 243 | |
casper | aebb1c9 | 2006-02-21 00:59:39 -0800 | [diff] [blame] | 244 | /^#/ || /^$/ { |
Cody Peter Mello | e9753c8 | 2019-08-21 17:17:53 -0700 | [diff] [blame^] | 245 | next; |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 246 | } |
| 247 | |
Nathan Bush | 1099afd | 2010-06-24 15:03:22 -0700 | [diff] [blame] | 248 | { |
| 249 | # For each input line, nawk automatically assigns the complete |
| 250 | # line to $0 and also splits the line at field separators and |
| 251 | # assigns each field to a variable $1..$n. Assignment to $0 |
| 252 | # re-splits the line into the field variables. Conversely, |
| 253 | # assgnment to a variable $1..$n will cause $0 to be recomputed |
| 254 | # from the field variable values. |
| 255 | # |
| 256 | # This code adds awareness of escaped field separators by using |
| 257 | # a custom function to split the line into a temporary array. |
| 258 | # It assigns the empty string to $0 to clear any excess field |
| 259 | # variables, and assigns the desired elements of the temporary |
| 260 | # array back to the field variables $1..$7. |
| 261 | # |
| 262 | # Subsequent code must not assign directly to $0 or the fields |
| 263 | # will be re-split without regard to escaped field separators. |
| 264 | split_escape($0, f, ":"); |
| 265 | $0 = ""; |
| 266 | $1 = f[1]; |
| 267 | $2 = f[2]; |
| 268 | $3 = f[3]; |
| 269 | $4 = f[4]; |
| 270 | $5 = f[5]; |
| 271 | $6 = f[6]; |
| 272 | $7 = f[7]; |
| 273 | } |
| 274 | |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 275 | type == "auth" { |
| 276 | key = $1 ":" $2 ":" $3 ; |
Nathan Bush | 8d0bff0 | 2010-08-12 14:07:03 -0700 | [diff] [blame] | 277 | if (pass == 1) { |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 278 | short_comment[key] = $4 ; |
| 279 | long_comment[key] = $5; |
| 280 | record[key] = $6; |
Nathan Bush | 8d0bff0 | 2010-08-12 14:07:03 -0700 | [diff] [blame] | 281 | } else if (pass == 2) { |
| 282 | delete short_comment[key]; |
| 283 | delete long_comment[key]; |
| 284 | delete record[key]; |
| 285 | } else if (pass == 3) { |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 286 | if ( $4 != "" ) { |
| 287 | short_comment[key] = $4 ; |
| 288 | } |
| 289 | if ( $5 != "" ) { |
| 290 | long_comment[key] = $5 ; |
| 291 | } |
Nathan Bush | 8d0bff0 | 2010-08-12 14:07:03 -0700 | [diff] [blame] | 292 | record[key] = merge_attrs(record[key], $6); |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 293 | } |
| 294 | } |
| 295 | |
| 296 | type == "prof" { |
| 297 | key = $1 ":" $2 ":" $3 ; |
Nathan Bush | 8d0bff0 | 2010-08-12 14:07:03 -0700 | [diff] [blame] | 298 | if (pass == 1) { |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 299 | comment[key] = $4; |
| 300 | record[key] = $5; |
Nathan Bush | 8d0bff0 | 2010-08-12 14:07:03 -0700 | [diff] [blame] | 301 | } else if (pass == 2) { |
| 302 | delete comment[key]; |
| 303 | delete record[key]; |
| 304 | } else if (pass == 3) { |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 305 | if ( $4 != "" ) { |
| 306 | comment[key] = $4 ; |
| 307 | } |
casper | aebb1c9 | 2006-02-21 00:59:39 -0800 | [diff] [blame] | 308 | if (key != "::") { |
Nathan Bush | 8d0bff0 | 2010-08-12 14:07:03 -0700 | [diff] [blame] | 309 | record[key] = merge_attrs(record[key], $5); |
casper | aebb1c9 | 2006-02-21 00:59:39 -0800 | [diff] [blame] | 310 | } |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 311 | } |
| 312 | } |
| 313 | |
| 314 | type == "exec" { |
| 315 | key = $1 ":" $2 ":" $3 ":" $4 ":" $5 ":" $6 ; |
Nathan Bush | 8d0bff0 | 2010-08-12 14:07:03 -0700 | [diff] [blame] | 316 | if (pass == 1) { |
| 317 | record[key] = $7; |
| 318 | } else if (pass == 2) { |
| 319 | # For exec_attr, deletion is based on the 'name' field only, |
| 320 | # so that all old entries for the profile are removed. |
| 321 | for (oldkey in record) { |
| 322 | split_escape(oldkey, oldkey_fields, ":"); |
| 323 | if (oldkey_fields[1] == $1) |
| 324 | delete record[oldkey]; |
| 325 | } |
| 326 | } else if (pass == 3) { |
| 327 | # Substitute new entries, do not merge. |
| 328 | record[key] = $7; |
| 329 | } |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 330 | } |
| 331 | |
| 332 | type == "user" { |
| 333 | key = $1 ":" $2 ":" $3 ":" $4 ; |
Nathan Bush | 8d0bff0 | 2010-08-12 14:07:03 -0700 | [diff] [blame] | 334 | if (pass == 1) { |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 335 | record[key] = $5; |
Nathan Bush | 8d0bff0 | 2010-08-12 14:07:03 -0700 | [diff] [blame] | 336 | } else if (pass == 2) { |
| 337 | if ($1 != "root") |
| 338 | delete record[key]; |
| 339 | } else if (pass == 3) { |
| 340 | record[key] = merge_attrs(record[key], $5); |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 341 | } |
| 342 | } |
| 343 | |
| 344 | END { |
| 345 | for (key in record) { |
| 346 | if (type == "prof") { |
casper | aebb1c9 | 2006-02-21 00:59:39 -0800 | [diff] [blame] | 347 | if (key != "::") { |
| 348 | print key ":" comment[key] ":" record[key]; |
| 349 | } |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 350 | } else |
| 351 | if (type == "auth") { |
| 352 | print key ":" short_comment[key] ":" \ |
| 353 | long_comment[key] ":" record[key]; |
| 354 | } else |
| 355 | print key ":" record[key]; |
| 356 | } |
| 357 | } |
| 358 | |
| 359 | function merge_attrs(old, new, cnt, new_cnt, i, j, list, new_list, keyword) |
| 360 | { |
Nathan Bush | 1099afd | 2010-06-24 15:03:22 -0700 | [diff] [blame] | 361 | cnt = split_escape(old, list, ";"); |
| 362 | new_cnt = split_escape(new, new_list, ";"); |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 363 | for (i = 1; i <= new_cnt; i++) { |
| 364 | keyword = substr(new_list[i], 1, index(new_list[i], "=")-1); |
| 365 | for (j = 1; j <= cnt; j++) { |
| 366 | if (match(list[j], "^" keyword "=")) { |
| 367 | list[j] = merge_values(keyword, list[j], |
| 368 | new_list[i]); |
| 369 | break; |
| 370 | } |
| 371 | } |
| 372 | if (j > cnt) |
| 373 | list[++cnt] = new_list[i]; |
| 374 | } |
| 375 | |
| 376 | return unsplit(list, cnt, ";"); \ |
| 377 | } |
| 378 | |
| 379 | function merge_values(keyword, old, new, cnt, new_cnt, i, j, list, new_list, d) |
| 380 | { |
Nathan Bush | 8d0bff0 | 2010-08-12 14:07:03 -0700 | [diff] [blame] | 381 | # Keywords with multivalued attributes that are subject to merging |
| 382 | # are processed by the algorithm implemented further below. |
| 383 | # Otherwise, the keyword is not subject to merging, and: |
| 384 | # For user_attr, the existing value is retained. |
| 385 | # For any other file, the new value is substituted. |
| 386 | if (keyword_behavior[type, keyword] != "merge") { |
| 387 | if (type == "user") { |
| 388 | return old; |
| 389 | } else { |
| 390 | return new; |
| 391 | } |
| 392 | } |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 393 | |
| 394 | cnt = split(substr(old, length(keyword)+2), list, ","); |
| 395 | new_cnt = split(substr(new, length(keyword)+2), new_list, ","); |
| 396 | |
| 397 | # If the existing list contains "All", remove it and add it |
| 398 | # to the new list; that way "All" will appear at the only valid |
| 399 | # location, the end of the list. |
| 400 | if (keyword == "profiles") { |
| 401 | d = 0; |
| 402 | for (i = 1; i <= cnt; i++) { |
| 403 | if (list[i] != "All") |
| 404 | list[++d] = list[i]; |
| 405 | } |
| 406 | if (cnt != d) { |
| 407 | new_list[++new_cnt] = "All"; |
| 408 | cnt = d; |
| 409 | } |
| 410 | } |
| 411 | for (i = 1; i <= new_cnt; i++) { |
| 412 | for (j = 1; j <= cnt; j++) { |
| 413 | if (list[j] == new_list[i]) |
| 414 | break; |
| 415 | } |
| 416 | if (j > cnt) |
| 417 | list[++cnt] = new_list[i]; |
| 418 | } |
| 419 | |
| 420 | return keyword "=" unsplit(list, cnt, ","); |
| 421 | } |
| 422 | |
Nathan Bush | 1099afd | 2010-06-24 15:03:22 -0700 | [diff] [blame] | 423 | # This function is similar to the nawk built-in split() function, |
| 424 | # except that a "\" character may be used to escape any subsequent |
| 425 | # character, so that the escaped character will not be treated as a |
| 426 | # field separator or as part of a field separator regular expression. |
| 427 | # The "\" characters will remain in the elements of the output array |
| 428 | # variable upon completion. |
| 429 | function split_escape(str, list, fs, cnt, saved, sep) |
| 430 | { |
| 431 | # default to global FS |
| 432 | if (fs == "") |
| 433 | fs = FS; |
| 434 | # initialize empty list, cnt, saved |
| 435 | split("", list, " "); |
| 436 | cnt = 0; |
| 437 | saved = ""; |
| 438 | # track whether last token was a field separator |
| 439 | sep = 0; |
| 440 | # nonzero str length indicates more string left to scan |
| 441 | while (length(str)) { |
| 442 | if (match(str, fs) == 1) { |
| 443 | # field separator, terminates current field |
| 444 | list[++cnt] = saved; |
| 445 | saved = ""; |
| 446 | str = substr(str, RLENGTH + 1); |
| 447 | sep = 1; |
| 448 | } else if (substr(str, 1, 1) == "\\") { |
| 449 | # escaped character |
| 450 | saved = saved substr(str, 1, 2); |
| 451 | str = substr(str, 3); |
| 452 | sep = 0; |
| 453 | } else { |
| 454 | # regular character |
| 455 | saved = saved substr(str, 1, 1); |
| 456 | str = substr(str, 2); |
| 457 | sep = 0; |
| 458 | } |
| 459 | } |
| 460 | # if required, append final field to list |
| 461 | if (sep || length(saved)) |
| 462 | list[++cnt] = saved; |
| 463 | |
| 464 | return cnt; |
| 465 | } |
| 466 | |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 467 | function unsplit(list, cnt, delim, str) |
| 468 | { |
| 469 | str = list[1]; |
| 470 | for (i = 2; i <= cnt; i++) |
| 471 | str = str delim list[i]; |
| 472 | return str; |
| 473 | }' \ |
Nathan Bush | 8d0bff0 | 2010-08-12 14:07:03 -0700 | [diff] [blame] | 474 | type=$1 $nawk_pass1 $nawk_pass2 $nawk_pass3 > $4.unsorted |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 475 | rc=$? |
| 476 | $sort_cmd < $4.unsorted >> $4 |
| 477 | return $rc |
| 478 | } |
| 479 | |
| 480 | # $1 is the merged file |
| 481 | # $2 is the target file |
| 482 | # |
| 483 | commit() { |
Casper H.S. Dik | 58f7c25 | 2009-07-10 21:31:05 +0200 | [diff] [blame] | 484 | # Make sure that the last mv uses rename(2) by first moving to |
| 485 | # the same filesystem. |
| 486 | $mv_cmd $1 $2.$$ |
| 487 | $mv_cmd $2.$$ $2 |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 488 | return $? |
| 489 | } |
| 490 | |
| 491 | outfile="" |
| 492 | type="" |
| 493 | set_type_and_outfile() { |
| 494 | # |
| 495 | # Assumes basename $1 returns one of |
| 496 | # prof_attr, exec_attr, auth_attr, or user_attr |
| 497 | # |
| 498 | fname=`$basename_cmd $1` |
| 499 | type=`echo $fname | $sed_cmd -e s'/^\([a-z][a-z]*\)_attr$/\1/' ` |
| 500 | case "$type" in |
| 501 | "prof"|"exec"|"user"|"auth") ;; |
| 502 | *) return 2 ;; |
| 503 | esac |
| 504 | |
vp157776 | 7a3d041 | 2006-08-20 23:36:03 -0700 | [diff] [blame] | 505 | outfile=$tmp_dir/rbac_${PKGINST}_${fname}_merge.$$ |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 506 | |
| 507 | return 0 |
| 508 | } |
| 509 | |
| 510 | cleanup() { |
| 511 | $rm_cmd -f $outfile $outfile.old $outfile.new $outfile.unsorted |
| 512 | |
| 513 | return 0 |
| 514 | } |
| 515 | |
| 516 | exit_status=0 |
| 517 | |
| 518 | # main |
| 519 | |
| 520 | while read newfile oldfile ; do |
Casper H.S. Dik | 06d0f3f | 2009-06-19 17:45:11 +0200 | [diff] [blame] | 521 | if [ -n "$PKGINST" ] |
| 522 | then |
| 523 | # Install the file in the "fragment" directory. |
| 524 | mkdir -m 755 -p ${oldfile}.d |
| 525 | rm -f ${oldfile}.d/"$PKGINST" |
| 526 | cp $newfile ${oldfile}.d/"$PKGINST" |
| 527 | |
| 528 | # Make sure that it is marked read-only. |
| 529 | chmod a-w,a+r ${oldfile}.d/"$PKGINST" |
| 530 | |
| 531 | # We also execute the rest of the i.rbac script. |
| 532 | fi |
| 533 | |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 534 | if [ ! -f $oldfile ]; then |
| 535 | cp $newfile $oldfile |
| 536 | else |
Casper H.S. Dik | 06d0f3f | 2009-06-19 17:45:11 +0200 | [diff] [blame] | 537 | set_type_and_outfile $newfile || |
| 538 | set_type_and_outfile $oldfile |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 539 | if [ $? -ne 0 ]; then |
| 540 | echo "$0 : $newfile not one of" \ |
| 541 | " prof_attr, exec_attr, auth_attr, user_attr" |
| 542 | exit_status=2 |
| 543 | continue |
| 544 | fi |
| 545 | |
| 546 | dbmerge $type $oldfile $newfile $outfile |
| 547 | if [ $? -ne 0 ]; then |
| 548 | echo "$0 : failed to merge $newfile with $oldfile" |
| 549 | cleanup |
| 550 | exit_status=2 |
| 551 | continue |
| 552 | fi |
| 553 | |
casper | aebb1c9 | 2006-02-21 00:59:39 -0800 | [diff] [blame] | 554 | commit $outfile $oldfile |
stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 555 | if [ $? -ne 0 ]; then |
| 556 | echo "$0 : failed to mv $outfile to $2" |
| 557 | cleanup |
| 558 | exit_status=2 |
| 559 | continue |
| 560 | fi |
| 561 | |
| 562 | cleanup |
| 563 | fi |
| 564 | done |
| 565 | |
| 566 | if [ "$1" = "ENDOFCLASS" ]; then |
| 567 | exit 0 |
| 568 | fi |
| 569 | |
| 570 | exit $exit_status |