1*ead1f93eSLiane Praza#!/bin/sh 2*ead1f93eSLiane Praza# 3*ead1f93eSLiane Praza# CDDL HEADER START 4*ead1f93eSLiane Praza# 5*ead1f93eSLiane Praza# The contents of this file are subject to the terms of the 6*ead1f93eSLiane Praza# Common Development and Distribution License (the "License"). 7*ead1f93eSLiane Praza# You may not use this file except in compliance with the License. 8*ead1f93eSLiane Praza# 9*ead1f93eSLiane Praza# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*ead1f93eSLiane Praza# or http://www.opensolaris.org/os/licensing. 11*ead1f93eSLiane Praza# See the License for the specific language governing permissions 12*ead1f93eSLiane Praza# and limitations under the License. 13*ead1f93eSLiane Praza# 14*ead1f93eSLiane Praza# When distributing Covered Code, include this CDDL HEADER in each 15*ead1f93eSLiane Praza# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*ead1f93eSLiane Praza# If applicable, add the following below this CDDL HEADER, with the 17*ead1f93eSLiane Praza# fields enclosed by brackets "[]" replaced with your own identifying 18*ead1f93eSLiane Praza# information: Portions Copyright [yyyy] [name of copyright owner] 19*ead1f93eSLiane Praza# 20*ead1f93eSLiane Praza# CDDL HEADER END 21*ead1f93eSLiane Praza# 22*ead1f93eSLiane Praza# i.rbac 23*ead1f93eSLiane Praza# 24*ead1f93eSLiane Praza# Copyright 2009 Sun Microsystems, Inc. All rights reserved. 25*ead1f93eSLiane Praza# Use is subject to license terms. 26*ead1f93eSLiane Praza# 27*ead1f93eSLiane Praza# class action script for "rbac" class files 28*ead1f93eSLiane Praza# installed by pkgadd 29*ead1f93eSLiane Praza# 30*ead1f93eSLiane Praza# Files in "rbac" class: 31*ead1f93eSLiane Praza# 32*ead1f93eSLiane Praza# /etc/security/{prof_attr,exec_attr,auth_attr} 33*ead1f93eSLiane Praza# /etc/user_attr 34*ead1f93eSLiane Praza# 35*ead1f93eSLiane Praza# Allowable exit codes 36*ead1f93eSLiane Praza# 37*ead1f93eSLiane Praza# 0 - success 38*ead1f93eSLiane Praza# 2 - warning or possible error condition. Installation continues. A warning 39*ead1f93eSLiane Praza# message is displayed at the time of completion. 40*ead1f93eSLiane Praza# 41*ead1f93eSLiane Praza 42*ead1f93eSLiane Prazaumask 022 43*ead1f93eSLiane Praza 44*ead1f93eSLiane Prazatmp_dir=${TMPDIR:-/tmp} 45*ead1f93eSLiane Praza 46*ead1f93eSLiane PrazaPATH="/usr/bin:/usr/sbin:${PATH}" 47*ead1f93eSLiane Prazaexport PATH 48*ead1f93eSLiane Praza 49*ead1f93eSLiane Prazabasename_cmd=basename 50*ead1f93eSLiane Prazacp_cmd=cp 51*ead1f93eSLiane Prazaegrep_cmd=egrep 52*ead1f93eSLiane Prazamv_cmd=mv 53*ead1f93eSLiane Prazanawk_cmd=nawk 54*ead1f93eSLiane Prazarm_cmd=rm 55*ead1f93eSLiane Prazased_cmd=sed 56*ead1f93eSLiane Prazasort_cmd=sort 57*ead1f93eSLiane Praza 58*ead1f93eSLiane Praza# $1 is the type 59*ead1f93eSLiane Praza# $2 is the "old/existing file" 60*ead1f93eSLiane Praza# $3 is the "new (to be merged)" file 61*ead1f93eSLiane Praza# $4 is the output file 62*ead1f93eSLiane Praza# returns 0 on success 63*ead1f93eSLiane Praza# returns 2 on failure if nawk fails with non-zero exit status 64*ead1f93eSLiane Praza# 65*ead1f93eSLiane Prazadbmerge() { 66*ead1f93eSLiane Praza# 67*ead1f93eSLiane Praza# Remove the ident lines. 68*ead1f93eSLiane Praza# 69*ead1f93eSLiane Praza ${egrep_cmd} -v '^#[pragma ]*ident' $2 > $4.old 2>/dev/null 70*ead1f93eSLiane Praza# 71*ead1f93eSLiane Praza# If the new file has a Sun copyright, remove the Sun copyright from the old 72*ead1f93eSLiane Praza# file. 73*ead1f93eSLiane Praza# 74*ead1f93eSLiane Praza newcr=`${egrep_cmd} '^# Copyright.*Sun Microsystems, Inc.' $3 \ 75*ead1f93eSLiane Praza 2>/dev/null` 76*ead1f93eSLiane Praza if [ -n "${newcr}" ]; then 77*ead1f93eSLiane Praza $sed_cmd -e '/^# Copyright.*Sun Microsystems, Inc./d' \ 78*ead1f93eSLiane Praza -e '/^# All rights reserved./d' \ 79*ead1f93eSLiane Praza -e '/^# Use is subject to license terms./d' \ 80*ead1f93eSLiane Praza $4.old > $4.$$ 2>/dev/null 81*ead1f93eSLiane Praza $mv_cmd $4.$$ $4.old 82*ead1f93eSLiane Praza fi 83*ead1f93eSLiane Praza# 84*ead1f93eSLiane Praza# If the new file has the CDDL, remove it from the old file. 85*ead1f93eSLiane Praza# 86*ead1f93eSLiane Praza newcr=`${egrep_cmd} '^# CDDL HEADER START' $3 2>/dev/null` 87*ead1f93eSLiane Praza if [ -n "${newcr}" ]; then 88*ead1f93eSLiane Praza $sed_cmd -e '/^# CDDL HEADER START/,/^# CDDL HEADER END/d' \ 89*ead1f93eSLiane Praza $4.old > $4.$$ 2>/dev/null 90*ead1f93eSLiane Praza $mv_cmd $4.$$ $4.old 91*ead1f93eSLiane Praza fi 92*ead1f93eSLiane Praza# 93*ead1f93eSLiane Praza# Remove empty lines and multiple instances of these comments: 94*ead1f93eSLiane Praza# 95*ead1f93eSLiane Praza $sed_cmd -e '/^# \/etc\/security\/exec_attr/d' -e '/^#$/d' \ 96*ead1f93eSLiane Praza -e '/^# execution attributes for profiles./d' \ 97*ead1f93eSLiane Praza -e '/^# See exec_attr(4)/d' \ 98*ead1f93eSLiane Praza -e '/^# \/etc\/user_attr/d' \ 99*ead1f93eSLiane Praza -e '/^# user attributes. see user_attr(4)/d' \ 100*ead1f93eSLiane Praza -e '/^# \/etc\/security\/prof_attr/d' \ 101*ead1f93eSLiane Praza -e '/^# profiles attributes. see prof_attr(4)/d' \ 102*ead1f93eSLiane Praza -e '/^# See prof_attr(4)/d' \ 103*ead1f93eSLiane Praza -e '/^# \/etc\/security\/auth_attr/d' \ 104*ead1f93eSLiane Praza -e '/^# authorizations. see auth_attr(4)/d' \ 105*ead1f93eSLiane Praza -e '/^# authorization attributes. see auth_attr(4)/d' \ 106*ead1f93eSLiane Praza $4.old > $4.$$ 107*ead1f93eSLiane Praza $mv_cmd $4.$$ $4.old 108*ead1f93eSLiane Praza# 109*ead1f93eSLiane Praza# Retain old and new header comments. 110*ead1f93eSLiane Praza# 111*ead1f93eSLiane Praza $sed_cmd -n -e '/^[^#]/,$d' -e '/^##/,$d' -e p $4.old > $4 112*ead1f93eSLiane Praza $rm_cmd $4.old 113*ead1f93eSLiane Praza $sed_cmd -n -e '/^[^#]/,$d' -e '/^##/,$d' -e p $3 >> $4 114*ead1f93eSLiane Praza# 115*ead1f93eSLiane Praza# Handle line continuations (trailing \) 116*ead1f93eSLiane Praza# 117*ead1f93eSLiane Praza $sed_cmd \ 118*ead1f93eSLiane Praza -e '/\\$/{N;s/\\\n//;}' -e '/\\$/{N;s/\\\n//;}' \ 119*ead1f93eSLiane Praza -e '/\\$/{N;s/\\\n//;}' -e '/\\$/{N;s/\\\n//;}' \ 120*ead1f93eSLiane Praza -e '/\\$/{N;s/\\\n//;}' -e '/\\$/{N;s/\\\n//;}' \ 121*ead1f93eSLiane Praza $2 > $4.old 122*ead1f93eSLiane Praza $sed_cmd \ 123*ead1f93eSLiane Praza -e '/\\$/{N;s/\\\n//;}' -e '/\\$/{N;s/\\\n//;}' \ 124*ead1f93eSLiane Praza -e '/\\$/{N;s/\\\n//;}' -e '/\\$/{N;s/\\\n//;}' \ 125*ead1f93eSLiane Praza -e '/\\$/{N;s/\\\n//;}' -e '/\\$/{N;s/\\\n//;}' \ 126*ead1f93eSLiane Praza $3 > $4.new 127*ead1f93eSLiane Praza# 128*ead1f93eSLiane Praza#!/usr/bin/nawk -f 129*ead1f93eSLiane Praza# 130*ead1f93eSLiane Praza# dbmerge type=[auth|prof|user|exec] old-file new-file 131*ead1f93eSLiane Praza# 132*ead1f93eSLiane Praza# Merge two versions of an RBAC database file. The output 133*ead1f93eSLiane Praza# consists of the lines from the new-file, while preserving 134*ead1f93eSLiane Praza# user customizations in the old-file. Specifically, the 135*ead1f93eSLiane Praza# keyword/value section of each record contains the union 136*ead1f93eSLiane Praza# of the entries found in both files. The value for each 137*ead1f93eSLiane Praza# keyword is the value from the new-file, except for three 138*ead1f93eSLiane Praza# keywords ("auths", "profiles", "roles") where the values 139*ead1f93eSLiane Praza# from the old and new files are merged. 140*ead1f93eSLiane Praza# 141*ead1f93eSLiane Praza# The output is run through sort except for the comments 142*ead1f93eSLiane Praza# which will appear first in the output. 143*ead1f93eSLiane Praza# 144*ead1f93eSLiane Praza# 145*ead1f93eSLiane Praza $nawk_cmd ' 146*ead1f93eSLiane Praza 147*ead1f93eSLiane PrazaBEGIN { 148*ead1f93eSLiane Praza FS=":" 149*ead1f93eSLiane Praza} 150*ead1f93eSLiane Praza 151*ead1f93eSLiane Praza/^#/ || /^$/ { 152*ead1f93eSLiane Praza continue; 153*ead1f93eSLiane Praza} 154*ead1f93eSLiane Praza 155*ead1f93eSLiane Prazatype == "auth" { 156*ead1f93eSLiane Praza key = $1 ":" $2 ":" $3 ; 157*ead1f93eSLiane Praza if (NR == FNR) { 158*ead1f93eSLiane Praza short_comment[key] = $4 ; 159*ead1f93eSLiane Praza long_comment[key] = $5; 160*ead1f93eSLiane Praza record[key] = $6; 161*ead1f93eSLiane Praza } 162*ead1f93eSLiane Praza else { 163*ead1f93eSLiane Praza if ( $4 != "" ) { 164*ead1f93eSLiane Praza short_comment[key] = $4 ; 165*ead1f93eSLiane Praza } 166*ead1f93eSLiane Praza if ( $5 != "" ) { 167*ead1f93eSLiane Praza long_comment[key] = $5 ; 168*ead1f93eSLiane Praza } 169*ead1f93eSLiane Praza print key ":" short_comment[key] ":" long_comment[key] ":" \ 170*ead1f93eSLiane Praza merge_attrs(record[key], $6); 171*ead1f93eSLiane Praza delete record[key]; 172*ead1f93eSLiane Praza } 173*ead1f93eSLiane Praza} 174*ead1f93eSLiane Praza 175*ead1f93eSLiane Prazatype == "prof" { 176*ead1f93eSLiane Praza key = $1 ":" $2 ":" $3 ; 177*ead1f93eSLiane Praza if (NR == FNR) { 178*ead1f93eSLiane Praza comment[key] = $4; 179*ead1f93eSLiane Praza record[key] = $5; 180*ead1f93eSLiane Praza } 181*ead1f93eSLiane Praza else { 182*ead1f93eSLiane Praza if ( $4 != "" ) { 183*ead1f93eSLiane Praza comment[key] = $4 ; 184*ead1f93eSLiane Praza } 185*ead1f93eSLiane Praza if (key != "::") { 186*ead1f93eSLiane Praza print key ":" comment[key] ":" \ 187*ead1f93eSLiane Praza merge_attrs(record[key], $5); 188*ead1f93eSLiane Praza } 189*ead1f93eSLiane Praza delete record[key]; 190*ead1f93eSLiane Praza } 191*ead1f93eSLiane Praza} 192*ead1f93eSLiane Praza 193*ead1f93eSLiane Prazatype == "exec" { 194*ead1f93eSLiane Praza key = $1 ":" $2 ":" $3 ":" $4 ":" $5 ":" $6 ; 195*ead1f93eSLiane Praza # Substitute new entries, do not merge. 196*ead1f93eSLiane Praza record[key] = $7; 197*ead1f93eSLiane Praza} 198*ead1f93eSLiane Praza 199*ead1f93eSLiane Prazatype == "user" { 200*ead1f93eSLiane Praza key = $1 ":" $2 ":" $3 ":" $4 ; 201*ead1f93eSLiane Praza if (NR == FNR) 202*ead1f93eSLiane Praza record[key] = $5; 203*ead1f93eSLiane Praza else { 204*ead1f93eSLiane Praza print key ":" merge_attrs(record[key], $5); 205*ead1f93eSLiane Praza delete record[key]; 206*ead1f93eSLiane Praza } 207*ead1f93eSLiane Praza} 208*ead1f93eSLiane Praza 209*ead1f93eSLiane PrazaEND { 210*ead1f93eSLiane Praza for (key in record) { 211*ead1f93eSLiane Praza if (type == "prof") { 212*ead1f93eSLiane Praza if (key != "::") { 213*ead1f93eSLiane Praza print key ":" comment[key] ":" record[key]; 214*ead1f93eSLiane Praza } 215*ead1f93eSLiane Praza } else 216*ead1f93eSLiane Praza if (type == "auth") { 217*ead1f93eSLiane Praza print key ":" short_comment[key] ":" \ 218*ead1f93eSLiane Praza long_comment[key] ":" record[key]; 219*ead1f93eSLiane Praza } else 220*ead1f93eSLiane Praza print key ":" record[key]; 221*ead1f93eSLiane Praza } 222*ead1f93eSLiane Praza} 223*ead1f93eSLiane Praza 224*ead1f93eSLiane Prazafunction merge_attrs(old, new, cnt, new_cnt, i, j, list, new_list, keyword) 225*ead1f93eSLiane Praza{ 226*ead1f93eSLiane Praza cnt = split(old, list, ";"); 227*ead1f93eSLiane Praza new_cnt = split(new, new_list, ";"); 228*ead1f93eSLiane Praza for (i = 1; i <= new_cnt; i++) { 229*ead1f93eSLiane Praza keyword = substr(new_list[i], 1, index(new_list[i], "=")-1); 230*ead1f93eSLiane Praza for (j = 1; j <= cnt; j++) { 231*ead1f93eSLiane Praza if (match(list[j], "^" keyword "=")) { 232*ead1f93eSLiane Praza list[j] = merge_values(keyword, list[j], 233*ead1f93eSLiane Praza new_list[i]); 234*ead1f93eSLiane Praza break; 235*ead1f93eSLiane Praza } 236*ead1f93eSLiane Praza } 237*ead1f93eSLiane Praza if (j > cnt) 238*ead1f93eSLiane Praza list[++cnt] = new_list[i]; 239*ead1f93eSLiane Praza } 240*ead1f93eSLiane Praza 241*ead1f93eSLiane Praza return unsplit(list, cnt, ";"); \ 242*ead1f93eSLiane Praza} 243*ead1f93eSLiane Praza 244*ead1f93eSLiane Prazafunction merge_values(keyword, old, new, cnt, new_cnt, i, j, list, new_list, d) 245*ead1f93eSLiane Praza{ 246*ead1f93eSLiane Praza if (keyword != "auths" && keyword != "profiles") 247*ead1f93eSLiane Praza return new; 248*ead1f93eSLiane Praza 249*ead1f93eSLiane Praza cnt = split(substr(old, length(keyword)+2), list, ","); 250*ead1f93eSLiane Praza new_cnt = split(substr(new, length(keyword)+2), new_list, ","); 251*ead1f93eSLiane Praza 252*ead1f93eSLiane Praza # If the existing list contains "All", remove it and add it 253*ead1f93eSLiane Praza # to the new list; that way "All" will appear at the only valid 254*ead1f93eSLiane Praza # location, the end of the list. 255*ead1f93eSLiane Praza if (keyword == "profiles") { 256*ead1f93eSLiane Praza d = 0; 257*ead1f93eSLiane Praza for (i = 1; i <= cnt; i++) { 258*ead1f93eSLiane Praza if (list[i] != "All") 259*ead1f93eSLiane Praza list[++d] = list[i]; 260*ead1f93eSLiane Praza } 261*ead1f93eSLiane Praza if (cnt != d) { 262*ead1f93eSLiane Praza new_list[++new_cnt] = "All"; 263*ead1f93eSLiane Praza cnt = d; 264*ead1f93eSLiane Praza } 265*ead1f93eSLiane Praza } 266*ead1f93eSLiane Praza for (i = 1; i <= new_cnt; i++) { 267*ead1f93eSLiane Praza for (j = 1; j <= cnt; j++) { 268*ead1f93eSLiane Praza if (list[j] == new_list[i]) 269*ead1f93eSLiane Praza break; 270*ead1f93eSLiane Praza } 271*ead1f93eSLiane Praza if (j > cnt) 272*ead1f93eSLiane Praza list[++cnt] = new_list[i]; 273*ead1f93eSLiane Praza } 274*ead1f93eSLiane Praza 275*ead1f93eSLiane Praza return keyword "=" unsplit(list, cnt, ","); 276*ead1f93eSLiane Praza} 277*ead1f93eSLiane Praza 278*ead1f93eSLiane Prazafunction unsplit(list, cnt, delim, str) 279*ead1f93eSLiane Praza{ 280*ead1f93eSLiane Praza str = list[1]; 281*ead1f93eSLiane Praza for (i = 2; i <= cnt; i++) 282*ead1f93eSLiane Praza str = str delim list[i]; 283*ead1f93eSLiane Praza return str; 284*ead1f93eSLiane Praza}' \ 285*ead1f93eSLiane Praza type=$1 $4.old $4.new > $4.unsorted 286*ead1f93eSLiane Praza rc=$? 287*ead1f93eSLiane Praza $sort_cmd < $4.unsorted >> $4 288*ead1f93eSLiane Praza return $rc 289*ead1f93eSLiane Praza} 290*ead1f93eSLiane Praza 291*ead1f93eSLiane Praza# $1 is the merged file 292*ead1f93eSLiane Praza# $2 is the target file 293*ead1f93eSLiane Praza# 294*ead1f93eSLiane Prazacommit() { 295*ead1f93eSLiane Praza # Make sure that the last mv uses rename(2) by first moving to 296*ead1f93eSLiane Praza # the same filesystem. 297*ead1f93eSLiane Praza $mv_cmd $1 $2.$$ 298*ead1f93eSLiane Praza $mv_cmd $2.$$ $2 299*ead1f93eSLiane Praza return $? 300*ead1f93eSLiane Praza} 301*ead1f93eSLiane Praza 302*ead1f93eSLiane Prazaoutfile="" 303*ead1f93eSLiane Prazatype="" 304*ead1f93eSLiane Prazaset_type_and_outfile() { 305*ead1f93eSLiane Praza # 306*ead1f93eSLiane Praza # Assumes basename $1 returns one of 307*ead1f93eSLiane Praza # prof_attr, exec_attr, auth_attr, or user_attr 308*ead1f93eSLiane Praza # 309*ead1f93eSLiane Praza fname=`$basename_cmd $1` 310*ead1f93eSLiane Praza type=`echo $fname | $sed_cmd -e s'/^\([a-z][a-z]*\)_attr$/\1/' ` 311*ead1f93eSLiane Praza case "$type" in 312*ead1f93eSLiane Praza "prof"|"exec"|"user"|"auth") ;; 313*ead1f93eSLiane Praza *) return 2 ;; 314*ead1f93eSLiane Praza esac 315*ead1f93eSLiane Praza 316*ead1f93eSLiane Praza outfile=$tmp_dir/rbac_${PKGINST}_${fname}_merge.$$ 317*ead1f93eSLiane Praza 318*ead1f93eSLiane Praza return 0 319*ead1f93eSLiane Praza} 320*ead1f93eSLiane Praza 321*ead1f93eSLiane Prazacleanup() { 322*ead1f93eSLiane Praza $rm_cmd -f $outfile $outfile.old $outfile.new $outfile.unsorted 323*ead1f93eSLiane Praza 324*ead1f93eSLiane Praza return 0 325*ead1f93eSLiane Praza} 326*ead1f93eSLiane Praza 327*ead1f93eSLiane Prazaexit_status=0 328*ead1f93eSLiane Praza 329*ead1f93eSLiane Praza# main 330*ead1f93eSLiane Praza 331*ead1f93eSLiane Prazawhile read newfile oldfile ; do 332*ead1f93eSLiane Praza if [ -n "$PKGINST" ] 333*ead1f93eSLiane Praza then 334*ead1f93eSLiane Praza # Install the file in the "fragment" directory. 335*ead1f93eSLiane Praza mkdir -m 755 -p ${oldfile}.d 336*ead1f93eSLiane Praza rm -f ${oldfile}.d/"$PKGINST" 337*ead1f93eSLiane Praza cp $newfile ${oldfile}.d/"$PKGINST" 338*ead1f93eSLiane Praza 339*ead1f93eSLiane Praza # Make sure that it is marked read-only. 340*ead1f93eSLiane Praza chmod a-w,a+r ${oldfile}.d/"$PKGINST" 341*ead1f93eSLiane Praza 342*ead1f93eSLiane Praza # We also execute the rest of the i.rbac script. 343*ead1f93eSLiane Praza fi 344*ead1f93eSLiane Praza 345*ead1f93eSLiane Praza if [ ! -f $oldfile ]; then 346*ead1f93eSLiane Praza cp $newfile $oldfile 347*ead1f93eSLiane Praza else 348*ead1f93eSLiane Praza set_type_and_outfile $newfile || 349*ead1f93eSLiane Praza set_type_and_outfile $oldfile 350*ead1f93eSLiane Praza if [ $? -ne 0 ]; then 351*ead1f93eSLiane Praza echo "$0 : $newfile not one of" \ 352*ead1f93eSLiane Praza " prof_attr, exec_attr, auth_attr, user_attr" 353*ead1f93eSLiane Praza exit_status=2 354*ead1f93eSLiane Praza continue 355*ead1f93eSLiane Praza fi 356*ead1f93eSLiane Praza 357*ead1f93eSLiane Praza dbmerge $type $oldfile $newfile $outfile 358*ead1f93eSLiane Praza if [ $? -ne 0 ]; then 359*ead1f93eSLiane Praza echo "$0 : failed to merge $newfile with $oldfile" 360*ead1f93eSLiane Praza cleanup 361*ead1f93eSLiane Praza exit_status=2 362*ead1f93eSLiane Praza continue 363*ead1f93eSLiane Praza fi 364*ead1f93eSLiane Praza 365*ead1f93eSLiane Praza commit $outfile $oldfile 366*ead1f93eSLiane Praza if [ $? -ne 0 ]; then 367*ead1f93eSLiane Praza echo "$0 : failed to mv $outfile to $2" 368*ead1f93eSLiane Praza cleanup 369*ead1f93eSLiane Praza exit_status=2 370*ead1f93eSLiane Praza continue 371*ead1f93eSLiane Praza fi 372*ead1f93eSLiane Praza 373*ead1f93eSLiane Praza cleanup 374*ead1f93eSLiane Praza fi 375*ead1f93eSLiane Prazadone 376*ead1f93eSLiane Praza 377*ead1f93eSLiane Prazaif [ "$1" = "ENDOFCLASS" ]; then 378*ead1f93eSLiane Praza exit 0 379*ead1f93eSLiane Prazafi 380*ead1f93eSLiane Praza 381*ead1f93eSLiane Prazaexit $exit_status 382