add apache to users group
// puts apache into the users group to allow dev teams etc..
sed -i 's/users:x:1000:admin/users:x:1000:admin,wwwrun/' /etc/group
2772 users tagging and storing useful source code snippets
Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world (or not, you can keep them private!)
sed -i 's/users:x:1000:admin/users:x:1000:admin,wwwrun/' /etc/group
# create further subdirectories if necessary ... #fi # #fi
You are going to create a system service agent account! Enter first name: clamavadmin Note: The last name is optional and defaults to "agent" if you just press <return>! Enter last name: Note: The user shell is optional and defaults to "/usr/bin/false" if you just press <return>! Enter user shell: /bin/bash Note: The home directory is optional and defaults to "/private/var/empty" if you just press <return>! Enter home directory: /private/var/clamavadmin System service agent account: clamavadmin successfully created! # test dscl . list /Groups GroupMembership dscl . -read /Users/clamavadmin dscl . -read /Groups/clamavadmin sudo ls -ld /private/var/clamavadmin sudo ls -l /private/var/clamavadmin/log/clamd.log sudo ls -ld /private/var/clamavadmin/tmp #sudo ls -l /private/var/clamavadmin/tmp/clamd # will be created later by man clamd sudo find /private/var/clamavadmin \( -type f -or -type d -or -type s \) -print0 | xargs -0 sudo ls -ldG # add clamavadmin to group admin and group $(logname) # add $(logname) to group clamavadmin sudo dscl . -append /Groups/admin GroupMembership clamavadmin sudo dscl . -append /Groups/$(logname) GroupMembership clamavadmin sudo dscl . -append /Groups/clamavadmin GroupMembership $(logname) #sudo dscl . -delete /Groups/admin GroupMembership clamavadmin #sudo dscl . -delete /Groups/$(logname) GroupMembership clamavadmin #sudo dscl . -delete /Groups/clamavadmin GroupMembership $(logname) # cf. http://textsnippets.com/posts/show/1402 dirmodes ~/Documents/ClamAV/Downloads/QueueDirectory # copy update_clamd_db.sh sudo cp /usr/local/sbin/update_clamd_db.sh /private/var/clamavadmin/update_clamd_db.sh sudo chown clamavadmin:clamavadmin /private/var/clamavadmin/update_clamd_db.sh sudo chmod 0750 /private/var/clamavadmin/update_clamd_db.sh ls -l /private/var/clamavadmin/update_clamd_db.sh # then change the following line in sudo nano /private/var/clamavadmin/update_clamd_db.sh /opt/local/bin/freshclam -u root # ... to read ... /opt/local/bin/freshclam -u clamavadmin # get an overview of your ClamAV file & folder permissions in /opt sudo find /opt \( -type f -or -type d \) -iregex ".*clam.*" -print0 | xargs -0 sudo ls -ldG # set new ClamAV file & folder permissions sudo find /opt \( -type f -or -type d \) -iregex ".*clam.*" -print0 | xargs -0 sudo chown clamavadmin:clamavadmin sudo find /opt \( -type f -or -type d \) -iregex ".*clam.*" -print0 | xargs -0 sudo chmod 0750 # reset permissions #sudo find /opt \( -type f -or -type d \) -iregex ".*clam.*" -print0 | xargs -0 sudo chown root:wheel #sudo find /opt \( -type f -or -type d \) -iregex ".*clam.*" -print0 | xargs -0 sudo chmod 0755 # test sudo find /opt \( -type f -or -type d \) -iregex ".*clam.*" -print0 | xargs -0 sudo ls -ldG sudo find /opt -not -user clamavadmin \( -type f -or -type d \) -iregex ".*clam.*" -print0 | xargs -0 sudo ls -ldG # then modify clamd.conf sudo nano /opt/local/etc/clamd.conf LogFileMaxSize 10M LogTime yes FixStaleSocket yes TCPAddr 127.0.0.1 MaxConnectionQueueLength 30 MaxThreads 20 ExitOnOOM yes ScanOLE2 yes # Microsoft Office documents and .msi files ScanPDF yes ArchiveMaxFileSize 100M ArchiveMaxCompressionRatio 0 #VirusEvent echo virus: %v >> /path/to/file.txt DatabaseDirectory /opt/local/share/clamav # hardcoded #LogFile /private/var/log/clamd.log #TemporaryDirectory /private/var/tmp #DatabaseDirectory /opt/local/share/clamav #LocalSocket /tmp/clamd #DatabaseDirectory /private/var/clamavadmin/share/clamav LogFile /private/var/clamavadmin/log/clamd.log TemporaryDirectory /private/var/clamavadmin/tmp LocalSocket /private/var/clamavadmin/tmp/clamd # modify net.clamav.clamd.plist sudo launchctl unload -w /Library/LaunchDaemons/net.clamav.clamd.plist 2>/dev/null sudo cp -p /Library/LaunchDaemons/net.clamav.clamd.plist /Library/LaunchDaemons/net.clamav.clamd.root-wheel sudo nano /Library/LaunchDaemons/net.clamav.clamd.plist <?xml version="1.0" encoding="UTF-8"?> DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.$"1.0"> sudo launchctl load -w /Library/LaunchDaemons/net.clamav.clamd.plist 2>/dev/null # modify net.clamav.update.clamd.db.plist sudo launchctl unload -w /Library/LaunchDaemons/net.clamav.update.clamd.db.plist 2>/dev/null sudo cp -p /Library/LaunchDaemons/net.clamav.update.clamd.db.plist /Library/LaunchDaemons/net.clamav.update.clamd.db.plist.root-wheel sudo nano /Library/LaunchDaemons/net.clamav.update.clamd.db.plist "1.0" encoding="UTF-8"?> "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.$ <plist version="1.0"> <dict> <key>Disabledkey> Disabled GroupName clamavadmin Label net.clamav.clamd ProgramArguments /opt/local/sbin/clamd -c /opt/local/etc/clamd.conf RunAtLoad UserName clamavadmin /> <key>GroupNamekey> clamavadmin< /string> <key>Labelkey>net.clamav.update.clamd.db< /string> <key>ProgramArgumentskey>/private/var/clamavadmin/update_clamd_db.shstring> </array> <key>RunAtLoadkey> /> <key>StartIntervalkey> 20000< /integer> <key>UserNamekey>clamavadmin< /string> dict> sudo launchctl load -w /Library/LaunchDaemons/net.clamav.update.clamd.db.plist 2>/dev/null # watch clamd.log in a second Terminal window open /bin/bash sudo tail -n 50 -f /private/var/clamavadmin/log/clamd.log # now restart clamd if [[ -e "/private/var/clamavadmin/tmp/clamd" ]]; then sudo /bin/rm -f "/private/var/clamavadmin/tmp/clamd" ; fi sudo /opt/local/sbin/clamd -c /opt/local/etc/clamd.conf # test (sleep 3; echo PING; sleep 3; echo exit) | sudo telnet -u /private/var/clamavadmin/tmp/clamd echo PING | /opt/local/bin/socat - /private/var/clamavadmin/tmp/clamd # requires: sudo port install socat sudo find /private/var/clamavadmin \( -type f -or -type d -or -type s \) -print0 | xargs -0 sudo ls -ldG # /private/var/clamavadmin/tmp/clamd
#!/bin/bash if [[ "$(/usr/bin/whoami)" != "root" ]]; then printf '\nMust be run as root!\n\n'; exit 1; fi OPATH=$PATH export PATH=/usr/bin:/usr/sbin:/bin:/sbin OIFS=$IFS export IFS=$' \t\n' printf '\n\e[1mYou are going to create a system service agent account!\e[m\n\n' declare sudo=/usr/bin/sudo dscl=/usr/bin/dscl # first name printf "\e[1mEnter first name\e[m: " read fn # no spaces in names if [[ -z "$(printf -- "$fn" | /usr/bin/grep -Eo "^[^[:space:]]+$")" ]]; then printf '\nUse a name without spaces! \nPlease, try again!\n\n' exit 1 fi # name must not begin with a number if [[ -n "$(printf -- "$fn" | /usr/bin/grep -E "^[[:digit:]]")" ]]; then printf '\nName must not begin with a number! \nPlease, try again!\n\n' exit 1 fi # make sure the user name is unique new_user="$(/usr/bin/dscl . -search /Users name "$fn" 2>/dev/null)" if [[ -z "$new_user" ]]; then new_user="$fn" else printf "\nUser name already exists: $fn \nPlease, modify your name and try it again\x21\n\n" exit 1 fi # make sure the agent's primary group name is unique # note: the agent's primary group name is also based on the first name! new_group="$(/usr/bin/dscl . -search /Groups name "$fn")" if [[ -z "$new_group" ]]; then new_group="$fn" else printf "\nThe agent's primary group name already exists: $fn\x21 \nPlease, try again\x21\n\n" exit 1 fi # last name printf '\nNote: The \e[1mlast name\e[m is \e[1moptional\e[m and defaults to "agent" if you just press!\n ' printf "\e[1mEnter last name\e[m: " read ln if [[ -z "$ln" ]]; then ln="agent"; fi # no spaces in names if [[ -z "$(printf -- "$ln" | /usr/bin/grep -Eo "^[^[:space:]]+$")" ]]; then printf '\nUse a name without spaces! \nPlease, try again!\n\n' exit 1 fi # name must not begin with a number if [[ -n "$(printf -- "$ln" | /usr/bin/grep -E "^[[:digit:]]")" ]]; then printf '\nName must not begin with a number! \nPlease, try again!\n\n' exit 1 fi # user shell printf '\nNote: The \e[1muser shell\e[m is \e[1moptional\e[m and defaults to "/usr/bin/false" if you just press!\n' printf "\e[1mEnter user shell\e[m: " read sh if [[ -z "$sh" ]]; then sh="/usr/bin/false"; fi # test if user shell exists if [[ ! -e "$sh" ]]; then printf "\nUser shell does not exist: $sh\n\n" exit 1 fi # home directory printf '\nNote: The \e[1mhome directory\e[m is \e[1moptional\e[m and defaults to "/private/var/empty" if you just press!\n' printf "\e[1mEnter home directory\e[m: " read hd if [[ -z "$hd" ]]; then hd="/private/var/empty" elif [[ "${hd:0:1}" != '/' ]]; then printf '\nThe home directory path does not begin with a slash "/".\nPlease, try again!\n\n' exit 1 elif [[ -e "$hd" ]]; then printf "\nHome directory already exists: $hd \nPlease, try again\x21\n\n" exit 1 fi hd=${hd%/} # remove a trailing slash character "/" if necessary # get unique id numbers (uid, gid) unset -v new_uid new_gid i declare -i new_uid=0 new_gid=0 i=100 while [[ $i -lt 500 ]]; do # try to get $new_uid and $new_gid between 100 and 500 i=$[i+1] if [[ -z "$(/usr/bin/dscl . -search /Users uid $i)" ]] && [[ -z "$(/usr/bin/dscl . -search /Groups gid $i)" ]]; then new_uid=$i new_gid=$i break fi done if [[ $new_uid -eq 0 ]] || [[ $new_gid -eq 0 ]]; then # get $new_uid and $new_gid greater than 500 i=500 idvar=0 while [[ $idvar -eq 0 ]]; do i=$[i+1] if [[ -z "$(/usr/bin/dscl . -search /Users uid $i)" ]] && [[ -z "$(/usr/bin/dscl . -search /Groups gid $i)" ]]; then new_uid=$i new_gid=$i idvar=1 #break fi done fi if [[ $new_uid -eq 0 ]] || [[ $new_gid -eq 0 ]]; then printf 'Getting unique id numbers (uid, gid) failed!\n'; exit 1; fi # check once again ... if [[ $new_uid -eq $new_gid ]] && [[ "$new_user" == "$fn" ]] && [[ "$new_group" == "$fn" ]]; then # create home directory if [[ "$hd" != "/private/var/empty" ]]; then $sudo /bin/mkdir -p "$hd" fi # create the agent's primary group $sudo /usr/sbin/dseditgroup -o create -r "$fn $ln" -i $new_gid "$new_group" $sudo $dscl . -append "/Groups/$new_group" passwd "*" # create the system service agent $sudo $dscl . -create /Users/$new_user $sudo $dscl . -append /Users/$new_user RealName "$fn $ln" $sudo $dscl . -append /Users/$new_user uid $new_uid $sudo $dscl . -append /Users/$new_user gid $new_gid $sudo $dscl . -append /Users/$new_user shell "$sh" $sudo $dscl . -append /Users/$new_user home "$hd" $sudo $dscl . -create /Users/$new_user passwd "*" $sudo $dscl . -append "/Groups/$new_group" GroupMembership "$new_user" # add new agent to the agent's primary group #$sudo /usr/sbin/dseditgroup -o edit -a "$new_group" -t user "$new_user" else printf "\nConfiguration of system service agent account: $fn failed\x21 \nPlease, try again\x21\n\n" exit 1 fi # create further subdirectories if necessary #if [[ "$hd" != "/private/var/empty" ]]; then # #if [[ "$new_user" == "clamavadmin" ]]; then # # additional subdirectories for the clamavadmin system service agent account # $sudo /bin/mkdir -p "$hd"/log # $sudo /usr/bin/touch "$hd"/log/clamd.log # $sudo /bin/mkdir -p "$hd"/tmp # $sudo /bin/mkdir -p "$hd"/share/clamav # $sudo /usr/sbin/chown -R $new_user:$new_user "$hd" # $sudo /bin/chmod -R 750 "$hd" #fi # #fi printf "\nSystem service agent account: \e[1m$fn\e[m successfully created\x21\n\n" export IFS=$OIFS export PATH=$OPATH exit 0 #--------------------------- # test dscl . list /Users dscl . -read /Users/dscl . list /Groups dscl . -read /Groups/ dscl . list /Groups GroupMembership
#!/bin/bash if [[ "$(/usr/bin/whoami)" != "root" ]]; then printf '\nMust be run as root!\n\n'; exit 1; fi OPATH=$PATH export PATH=/usr/bin:/usr/sbin:/bin:/sbin OIFS=$IFS export IFS=$' \t\n' declare sudo=/usr/bin/sudo printf "\n\e[1mDelete system service agent account\e[m: " read agent if [[ -z "$agent" ]]; then printf '\nNo name for system service agent specified! Please, try again!\n\n'; exit 1; fi # make sure the agent exists agenttest="$(/usr/bin/dscl . -search /Users name "$agent")" if [[ -z "$agenttest" ]]; then printf "\nThe system service agent does not exist: $agent\n\n"; exit 1; fi # find the agent's home directory home=$(/usr/bin/dscl . -read /Users/$agent home | awk -F ': ' '{ print $NF; }' ) # get the agent's group memberships groups_of_agent="$(/usr/bin/id -Gn $agent)" # delete the agent's group memberships if [[ $? -eq 0 ]] && [[ -n "$(/usr/bin/dscl . -search /Groups GroupMembership "$agent")" ]]; then for group in $groups_of_agent; do $sudo /usr/bin/dscl . -delete "/Groups/$group" GroupMembership "$agent" #$sudo /usr/sbin/dseditgroup -o edit -d "$agent" -t user "$group" done fi # delete the agent's primary group if [[ -n "$(/usr/bin/dscl . -search /Groups name "$agent")" ]]; then $sudo /usr/sbin/dseditgroup -o delete "$agent" fi # if the agent's primary group has not been deleted ... if [[ -n "$(/usr/bin/dscl . -search /Groups name "$agent")" ]]; then printf " \e[1mWarning\e[m: The group memberships of the system service agent \e[1m$agent\e[m have been deleted\x21 groups_of_agent: $groups_of_agent The agent's primary group \e[1m$agent\e[m, however, has not been deleted\x21 Please, try again\x21 Exiting ...\n " exit 1 fi # find the GeneratedUID of the agent and remove the password hash file # from /private/var/db/shadow/hash/# sudo ls -a /private/var/db/shadow/hash # sudo ls -l /private/var/db/shadow/hash/ guid="$(/usr/bin/dscl . -read "/Users/$agent" GeneratedUID | /usr/bin/awk '{print $NF;}')" if [[ -f "/private/var/db/shadow/hash/$guid" ]]; then $sudo /bin/rm -f /private/var/db/shadow/hash/$guid fi # delete the agent $sudo /usr/bin/dscl . -delete "/Users/$agent" # make a backup if [[ -d "$home" ]] && [[ "$home" != "/private/var/empty" ]]; then $sudo /usr/bin/ditto -rsrc -c -k "$home" "${home}-archive-$(/bin/date).zip" fi # remove the agent's home directory if [[ -d "$home" ]] && [[ "$home" != "/private/var/empty" ]]; then $sudo /bin/rm -rf "$home" fi printf "\nSystem service agent account: \e[1m$agent\e[m successfully deleted\x21\n\n" export IFS=$OIFS export PATH=$OPATH exit 0
function showifs() { printf "%q\n" "${IFS}" # cf. help printf #echo -n "${IFS}" | ruby -n -e 'p $_.to_s' } showifs # show the Internal Field Separator
function dirmodes() { declare dir user group mods declare -a ar ret declare -i size i n dir="$@" if [[ ! -e "$dir" ]]; then printf "%s\n" "Directory (or file) does not exist: $dir"; return 1; fi dir=${dir%/} # remove a trailing slash character "/" if necessary OIFS="$IFS" export IFS=$'\n' i=-1 while [[ -n "$dir" ]]; do i=$[i+1] user="$(/usr/bin/stat -f "%Su" "$dir")" group="$(/usr/bin/stat -f "%Sg" "$dir")" mods="$(/usr/bin/stat -f "%p" "$dir")" mods="${mods: -4}" #mods="$(/usr/bin/stat -f "%p" "$dir" | /usr/bin/grep -Eo "[[:digit:]]{4}$")" ar[$i]="$(printf "%-35s %-50s\n" $user:$group:$mods $dir)" dir="$(/usr/bin/dirname "$dir")" if [[ "$dir" == '/' ]]; then i=$[i+1] ar[$i]="$(printf "%-35s %-50s\n" $user:$group:$mods $dir)" dir="" fi done # get number of array elements size=$(/bin/expr ${#ar[@]} - 1 ) n=-1 for (( i=$size; i>=0; i-- )); do # reverse the array n=$[n+1] ret[$n]=${ar[$i]} printf "%s\n" "$(printf -- "${ar[$i]}" | tr -d '\r\n')" done export IFS="$OIFS" return 0 }
# get the ClamAV icon cd ~/Desktop curl -L -O http://freshmeat.net/redir/clamav/29355/url_tgz/clamav-0.92.tar.gz tar -xzf clamav-0.92.tar.gz cd clamav-0.92 sudo cp ~/Desktop/clamav-0.92/docs/html/img2.png /usr/local/bin/CocoaDialog.app/Contents/Resources/clamav.png #sudo sips -i /usr/local/bin/CocoaDialog.app/Contents/Resources/clamav.png sudo chown -R root:wheel /usr/local/bin/CocoaDialog.app sudo chmod -R 0755 /usr/local/bin/CocoaDialog.app open -a Automator #---------------------------------------------------- Drag or add actions here to build your workflow: Library: Finder -> Action: Get Selected Finder Items Library: Automator -> Action: Run Shell Script - Shell: /bin/bash - Pass input: as arguments cocoadialog="/usr/local/bin/CocoaDialog.app/Contents/MacOS/CocoaDialog" CD_Resources="/usr/local/bin/CocoaDialog.app/Contents/Resources" for f in "$@"; do /opt/local/bin/clamdscan --quiet "$f" 2>/dev/null return_code=$? if [[ $return_code -eq 0 ]]; then /usr/bin/say OK $cocoadialog bubble --no-timeout --x-placement center --y-placement center --background-top "00FF00" \ --background-bottom "00FF99" --icon-file $CD_Resources/clamav.png --title "Scanned item is OK!" \ --text "$f" elif [[ $return_code -eq 1 ]]; then /usr/bin/say "virus alert" $cocoadialog bubble --no-timeout --x-placement center --y-placement center --background-top "FF0000" \ --background-bottom "FF0066" --icon-file $CD_Resources/clamav.png --title "WARNING: VIRUS ALERT!!!" \ --text "$f" else $cocoadialog bubble --no-timeout --x-placement center --y-placement center --background-top "FFCC00" \ --background-bottom "FFCC33" --icon-file $CD_Resources/clamav.png --title "ClamAV virus scan failed!" \ --text "Please, check your ClamAV setup! Return code of man clamdscan: $return_code" exit 1 fi done exit 0 #---------------------------------------------------- # save the virusscan Automator workflow as a contextual menu item Automator -> File -> Save As Plug-in ... -> Save Plug-in As: virusscan -> Plug-in for: Finder -> Save open ~/Library/Workflows/Applications/Finder/virusscan.workflow # test some files in ... open ~/Desktop/clamav-0.92/test
cd ~/Desktop curl -L -O http://prdownloads.sourceforge.net/cocoadialog/CocoaDialog-2.1.1.dmg hdiutil mount CocoaDialog-2.1.1.dmg sudo mkdir -p /usr/local/bin sudo ditto -rsrc /Volumes/CocoaDialog/CocoaDialog.app /usr/local/bin/CocoaDialog.app sudo chown -R root:wheel /usr/local/bin/CocoaDialog.app sudo chmod -R 0755 /usr/local/bin/CocoaDialog.app hdiutil unmount /Volumes/CocoaDialog alias cocoadialog=/usr/local/bin/CocoaDialog.app/Contents/MacOS/CocoaDialog # cf. http://cocoadialog.sourceforge.net/examples/bubble.sh.txt cocoadialog bubble --no-timeout --x-placement center --y-placement center --background-top "FF0000" --background-bottom "FF0066" \ --icon-file /usr/local/bin/CocoaDialog.app/Contents/Resources/info.icns --title "News" --text ''
find -x "$HOME" -type f -print0 2>/dev/null | while read -d $'\0' filename; do if [[ ${#filename} -lt 85 ]]; then printf -- "\r\e[0K$(printf -- "$filename" | tr -d '\n\r')"; else printf -- "\r\e[0K$(printf -- "$filename" | tr -d '\n\r' | sed -En 's/^(.{40}).*(.{40})$/\1.....\2/p')"; fi done; echo find -x "$HOME" -type f -print0 2>/dev/null | while read -d $'\0' filename; do i=$[i+1] if [[ ${#filename} -lt 85 ]]; then printf -- "\r\e[0K\e[1;32m$i\e[0m $(printf -- "$filename" | tr -d '\n\r')"; else printf -- "\r\e[0K\e[1;32m$i\e[0m $(printf -- "$filename" | tr -d '\n\r' | sed -En 's/^(.{40}).*(.{40})$/\1.....\2/p')"; fi done; echo
#!/bin/bash HOSTLIST="web2 web3 web4 vm1 dev" USER="mylogin" for H in $HOSTLIST; do echo -n "$H: " && ssh $USER@$H $* done
#!/bin/bash for file in `find / -type f -size +100000`; do ls -lh $file done
#!/bin/bash # cf. Adding a User From the Command Line, # http://developer.apple.com/documentation/Porting/Conceptual/PortingUnix/additionalfeatures/chapter_10_section_9.html if [[ "$(/usr/bin/whoami)" != "root" ]]; then printf '\nMust be run as root!\n\n'; exit 1; fi OPATH=$PATH export PATH=/usr/bin:/usr/sbin:/bin:/sbin OIFS=$IFS export IFS=$' \t\n' declare sudo=/usr/bin/sudo dscl=/usr/bin/dscl printf "\e[1mEnter first name\e[m: " read firstname # no spaces in names if [[ -z "$(printf -- "$firstname" | /usr/bin/grep -Eo "^[^[:space:]]+$")" ]]; then printf '\nUse a name without spaces! \nPlease, try again!\n\n' exit 1 fi # name must not begin with a number if [[ -n "$(printf -- "$firstname" | /usr/bin/grep -E "^[[:digit:]]")" ]]; then printf '\nName must not begin with a number! \nPlease, try again!\n\n' exit 1 fi # make sure the user name is unique new_user="$(/usr/bin/dscl . -search /Users name "$firstname" 2>/dev/null)" if [[ -z "$new_user" ]]; then new_user="$firstname" else printf "\nUser name already exists: $firstname \nPlease, modify your name and try it again\x21\n\n" # cf. man ascii for \x21 exit 1 fi # make sure the user's primary group name is unique # note: the user's primary group name is also based on the first name! new_group="$(/usr/bin/dscl . -search /Groups name "$firstname")" if [[ -z "$new_group" ]]; then new_group="$firstname" else printf "\nThe user's primary group name already exists: $firstname\x21 \nPlease, try again\x21\n\n" exit 1 fi # make sure there is no (file or) home directory of the same name already if [[ -e "/Users/$new_user" ]]; then printf "\nUser $new_user already exists at /Users/$new_user\x21 \nPlease, try again\x21\n\n" exit 1 fi # last name printf "\e[1mEnter last name\e[m: " read lastname # no spaces in names if [[ -z "$(printf -- "$lastname" | /usr/bin/grep -Eo "^[^[:space:]]+$")" ]]; then printf '\nUse a name without spaces! \nPlease, try again!\n\n' exit 1 fi # name must not begin with a number if [[ -n "$(printf -- "$lastname" | /usr/bin/grep -E "^[[:digit:]]")" ]]; then printf '\nName must not begin with a number! \nPlease, try again!\n\n' exit 1 fi # enter password printf "\e[1mEnter password\e[m: " stty_orig=$(/bin/stty -g) pass='' blank='false' while [[ "$blank" != "true" ]]; do /bin/stty -icanon -echo c=$(/bin/dd bs=6 count=1 2> /dev/null) # Check for a CR. if [[ -z "$(printf -- "$c" | /usr/bin/tr -d "\r\n")" ]]; then blank='true' else /bin/stty echo printf "*" pass="$pass$c" /bin/stty -echo fi done /bin/stty icanon echo /bin/stty "$stty_orig" passwd1="$pass" printf "\n" # check minimum password length: 6 if [[ -z "$(printf -- "$passwd1" | /usr/bin/grep -Eo "^([[:alnum:]]|[[:punct:]]){6,}$")" ]]; then printf '\nUse at least 6 characters (alphanumeric, punctuational) for your password! \nPlease, try again!\n\n' exit 1 fi # confirm password printf "\e[1mConfirm password\e[m: " stty_orig=$(/bin/stty -g) pass='' blank='false' while [[ "$blank" != "true" ]]; do /bin/stty -icanon -echo c=$(/bin/dd bs=6 count=1 2> /dev/null) # Check for a CR. if [[ -z "$(printf -- "$c" | /usr/bin/tr -d "\r\n")" ]]; then blank='true' else /bin/stty echo printf "*" pass="$pass$c" /bin/stty -echo fi done /bin/stty icanon echo /bin/stty "$stty_orig" passwd2="$pass" printf "\n" if [[ "$passwd1" != "$passwd2" ]]; then printf '\nPasswords do not match. \nPlease, try again!\n\n' exit 1 else printf '\nPassword confirmation was successful!\n\n' fi # get unique id numbers (uid, gid) that are greater than 500 unset -v i new_uid new_gid idvar declare -i new_uid=0 new_gid=0 i=500 idvar=0 while [[ $idvar -eq 0 ]]; do i=$[i+1] if [[ -z "$(/usr/bin/dscl . -search /Users uid $i)" ]] && [[ -z "$(/usr/bin/dscl . -search /Groups gid $i)" ]]; then new_uid=$i new_gid=$i idvar=1 #break fi done if [[ $new_uid -eq 0 ]] || [[ $new_gid -eq 0 ]]; then printf 'Getting unique id numbers (uid, gid) failed!\n'; exit 1; fi # old version # get unique id numbers (for uid, gid) by increasing the highest id number already in use by 1 #new_uid=$(($(/usr/bin/dscl . -list /Users uid | /usr/bin/awk '{print $NF;}' | /usr/bin/sort -n | /usr/bin/tail -n 1) + 1)) #new_gid=$(($(/usr/bin/dscl . -list /Groups gid | /usr/bin/awk '{print $NF;}' | /usr/bin/sort -n | /usr/bin/tail -n 1) + 1)) # make sure $new_uid and $new_gid are equal #if [[ $new_uid -ne $new_gid ]]; then # if [[ $new_uid -gt $new_gid ]]; then new_gid="$new_uid"; else new_uid=$new_gid; fi #fi # check once again ... if [[ $new_uid -eq $new_gid ]] && [[ "$new_user" == "$firstname" ]] && [[ "$new_group" == "$firstname" ]]; then # create the user's primary group $sudo /usr/sbin/dseditgroup -o create -r "$firstname $lastname" -i $new_gid "$new_group" $sudo $dscl . -append "/Groups/$new_group" passwd "*" $sudo $dscl . -create "/Users/$new_user" $sudo $dscl . -append "/Users/$new_user" RealName "$firstname $lastname" $sudo $dscl . -append "/Users/$new_user" NFSHomeDirectory "/Users/$new_user" ###$sudo $dscl . -append "/Users/$new_user" NFSHomeDirectory "/Local/Users/$new_user" $sudo $dscl . -append "/Users/$new_user" UserShell /bin/bash $sudo $dscl . -append "/Users/$new_user" PrimaryGroupID $new_gid $sudo $dscl . -append "/Users/$new_user" UniqueID $new_uid $sudo $dscl . -append "/Users/$new_user" hint "" $sudo $dscl . -append "/Users/$new_user" comment "user account \"$firstname $lastname\" created: $(/bin/date)" $sudo $dscl . -append "/Users/$new_user" picture "/Library/User Pictures/Animals/Butterfly.tif" $sudo $dscl . -append "/Users/$new_user" sharedDir Public $sudo $dscl . -passwd "/Users/$new_user" "$passwd1" # add some other properties that are usually set (Mac OS X 10.4) $sudo $dscl . -append "/Users/$new_user" _shadow_passwd "" $sudo $dscl . -append "/Users/$new_user" _writers_hint "$new_user" $sudo $dscl . -append "/Users/$new_user" _writers_real_name "$new_user" $sudo $dscl . -append "/Groups/$new_group" GroupMembership "$new_user" # add new user to the user's primary group #$sudo /usr/sbin/dseditgroup -o edit -a "$new_group" -t user "$new_user" $sudo $dscl . -append /Groups/staff GroupMembership "$new_user" # test: add new user to group staff # add the new user to the admin group (Mac OS X 10.4) # This should be part of a separate admin user account shell script or # at least require an additional user input prompt at the beginning! #$sudo $dscl . -append /Groups/admin GroupMembership "$new_user" #$sudo $dscl . -append /Groups/appserverusr GroupMembership "$new_user" #$sudo $dscl . -append /Groups/appserveradm GroupMembership "$new_user" # log out after running the script to see the new user account has been created $sudo /usr/sbin/createhomedir -l -u "$new_user" else printf "\nConfiguration of user account: $firstname failed\x21 \nPlease, try again\x21\n\n" exit 1 fi printf "\nUser account: $firstname successfully created\x21 \nYou can now log in to your new user account\x21\n\n" export IFS=$OIFS export PATH=$OPATH exit 0 #--------------------------- # test dscl . list /Users dscl . -read /Users/<firstname> dscl . list /Groups dscl . -read /Groups/<firstname> dscl . list /Groups GroupMembership
#!/bin/bash # cf. http://www.macos.utah.edu/documentation/authentication/dscl.html if [[ "$(/usr/bin/whoami)" != "root" ]]; then printf '\nMust be run as root!\n\n'; exit 1; fi OPATH=$PATH export PATH=/usr/bin:/usr/sbin:/bin:/sbin OIFS=$IFS export IFS=$' \t\n' declare sudo=/usr/bin/sudo printf "\e[1mDelete user account\e[m: " read user if [[ -z "$user" ]]; then printf '\nNo user specified! Please, try again!\n\n'; exit 1; fi # make sure the user exists usertest="$(/usr/bin/dscl . -search /Users name "$user" 2>/dev/null)" if [[ -z "$usertest" ]]; then printf "\nUser does not exist: $user\n\n"; exit 1; fi # get user's group memberships groups_of_user="$(/usr/bin/id -Gn $user)" if [[ $? -eq 0 ]] && [[ -n "$(/usr/bin/dscl . -search /Groups GroupMembership "$user")" ]]; then # delete the user's group memberships for group in $groups_of_user; do $sudo /usr/bin/dscl . -delete "/Groups/$group" GroupMembership "$user" #$sudo /usr/sbin/dseditgroup -o edit -d "$user" -t user "$group" done fi # delete the user's primary group if [[ -n "$(/usr/bin/dscl . -search /Groups name "$user")" ]]; then $sudo /usr/sbin/dseditgroup -o delete "$user" fi # if the user's primary group has not been deleted ... if [[ -n "$(/usr/bin/dscl . -search /Groups name "$user")" ]]; then printf " \e[1mWarning\e[m: The group memberships of the user \e[1m$user\e[m have been deleted\x21 groups_of_user: $groups_of_user The user's primary group \e[1m$user\e[m, however, has not been deleted\x21 Please, try again\x21 Exiting ...\n " exit 1 fi # find the GeneratedUID of the user and remove the password hash file # from /private/var/db/shadow/hash/# sudo ls -a /private/var/db/shadow/hash # sudo ls -l /private/var/db/shadow/hash/ guid="$(/usr/bin/dscl . -read "/Users/$user" GeneratedUID | /usr/bin/awk '{print $NF;}')" if [[ -f "/private/var/db/shadow/hash/$guid" ]]; then $sudo /bin/rm -f /private/var/db/shadow/hash/$guid fi # delete the user $sudo /usr/bin/dscl . -delete "/Users/$user" # make a backup if [[ -d "/Users/$user" ]]; then $sudo /usr/bin/ditto -rsrc -c -k "/Users/$user" "/Users/${user}-archive-$(/bin/date).zip" fi # remove the user's home directory if [[ -d "/Users/$user" ]]; then $sudo /bin/rm -rf "/Users/$user" fi export IFS=$OIFS export PATH=$OPATH exit 0
#!/bin/bash # cf. Creating password prompts using Bash, http://ubuntuforums.org/showthread.php?t=269592 stty_orig=$(stty -g) # Init some stuff... pass='' blank='false' # Main loop executed once for each char typed... while [[ "$blank" != "true" ]]; do stty -icanon -echo c=$(dd bs=6 count=1 2> /dev/null) # Check for a CR. if [ -z "$(printf -- "$c" | tr -d "\r\n")" ]; then blank='true' else stty echo echo -n "*" pass="$pass$c" stty -echo fi done stty icanon echo echo printf -- "$pass\n" stty "$stty_orig" exit 0
mkdir -p ~/Desktop/testdir touch ~/Desktop/testdir/f{1,2,3}.txt find -x ~/Desktop/testdir -print0 | xargs -0 stat -LF stat -x ~/Desktop/testdir/f1.txt which xattr # /opt/local/bin/xattr; sudo port install xattr (after installing MacPorts, http://www.macports.org/install.php) # store file permissions as additional Unix file metadata with xattr find -x ~/Desktop/testdir -print0 | while read -d $'\0' filename; do #find -x ~/Desktop/testdir -type f -or -type d -print0 | while read -d $'\0' filename; do fchmod="$(stat -f %p "$filename")"; \ fchown="$(stat -f %u:%g "$filename")"; \ xattr --set fchmod "$fchmod" "$filename"; \ xattr --set fchown "$fchown" "$filename"; \ #echo $fchown $fchmod; \ done find -x ~/Desktop/testdir -print0 | xargs -0 xattr --list find -x ~/Desktop/testdir -print0 | xargs -0 stat -LF # change file permissions & ownership sudo chown -R root:wheel ~/Desktop/testdir sudo chmod -R 700 ~/Desktop/testdir sudo find -x ~/Desktop/testdir -print0 | xargs -0 sudo stat -LF find -x ~/Desktop/testdir -print0 | xargs -0 xattr --list sudo find -x ~/Desktop/testdir -print0 | xargs -0 sudo xattr --list # restore file permissions & ownership sudo find -x ~/Desktop/testdir -print0 | while read -d $'\0' filename; do fchown="$(sudo xattr --get fchown "$filename" | awk '/fchown/ {print $2}')"; \ fchmod="$(sudo xattr --get fchmod "$filename" | awk '/fchmod/ {print $2}')"; \ sudo chown "$fchown" "$filename"; \ sudo chmod "$fchmod" "$filename"; \ #echo $fchown $fchmod; \ done find -x ~/Desktop/testdir -print0 | xargs -0 stat -LF find -x ~/Desktop/testdir -print0 | xargs -0 xattr --list
# convert from octal to symbolic format function o2s () { touch ~/.octal2symbolic; chmod -vv "$@" $_; ls -l $_ | awk '{print $1}'; rm -f ~/.octal2symbolic; } #function o2s () { touch ~/.octal2symbolic; chmod "$@" $_; ls -l $_ | awk '{print $1}'; rm -f ~/.octal2symbolic; } o2s 755 o2s 644 o2s 1744 o2s 0100751 # cf. man 2 stat (st_mode) o2s 0101751 # Cf. Bash 'umask' builtin doesn't set 'x' permissions? # http://archives.devshed.com/forums/unix-linux-135/bash-umask-builtin-doesn-t-set-x-permissions-372356.html UMASKO=$(umask) # 0022 help umask umask umask -p umask -S umask 0077 umask umask -S o2s 755 umask 0000 umask umask -S o2s 654 umask $UMASKO # convert from symbolic to octal format # default file permissions of temporary file: chmod 777 ~/.symbolic2octal function s2o () { touch ~/.symbolic2octal; chmod 777 $_; chmod "$@" $_; stat -f %p $_; rm -f ~/.symbolic2octal; } s2o a-x s2o u=rwx,g=rx,o=x s2o u=rwx,g=rx,o=x,+t
# download ClamAV sudo port install clamav # requires open firewall port 873 #sudo port uninstall clamav man clamd man clamd.conf man clamdscan man clamscan man freshclam # configure /opt/local/etc/freshclam.conf sudo cp -p /opt/local/etc/example-freshclam.conf /opt/local/etc/freshclam.conf sudo sed -i "" -e 's/^Example/#Example/' /opt/local/etc/freshclam.conf # comment out 'Example' line #sudo sed -i "" -e 's/^#Example/Example/' /opt/local/etc/freshclam.conf # uncomment 'Example' line sudo nano /opt/local/etc/freshclam.conf # make sure you are a member of the wheel and admin group id -G -n $(whoami) | grep -Eo 'wheel|admin' dseditgroup -o checkmember -m $(whoami) wheel; echo $? dseditgroup $(whoami) dseditgroup wheel dseditgroup admin sudo dscl . -append /Groups/wheel GroupMembership $(whoami) # add user to group if necessary #sudo dseditgroup -o edit -a $(whoami) -t user wheel # add user to group #sudo dscl . -delete /Groups/wheel GroupMembership $(whoami) # delete user from group #sudo dseditgroup -o edit -d $(whoami) -t user wheel # delete user from group sudo chown -R root:wheel /opt/local/share/clamav sudo chmod -R 0770 /opt/local/share/clamav freshclam # update virus database # test some clamav commands clamscan /path/to/file sudo clamscan -r /tmp sudo clamscan -r /private/var/tmp clamscan -r ~/Library/Caches clamscan -r ~/Library/Caches/java sudo clamscan -r ~/Library/Mail clamscan -r ~/Library # configure /opt/local/etc/clamd.conf # open /opt/local/etc # sudo nano /opt/local/etc/clamd.conf # cf. http://www.silvester.org.uk/OSX/configuring_clamd.html sudo cp -p /opt/local/etc/clamd.conf /opt/local/etc/clamd.conf.orig sudo sh -c ' cat << EOF > /opt/local/etc/clamd.conf LogFile /private/var/log/clamd.log LogFileMaxSize 10M LogTime yes TemporaryDirectory /private/var/tmp DatabaseDirectory /opt/local/share/clamav LocalSocket /tmp/clamd FixStaleSocket yes TCPAddr 127.0.0.1 MaxConnectionQueueLength 30 MaxThreads 20 ExitOnOOM yes ScanOLE2 yes # Microsoft Office documents and .msi files ScanPDF yes ArchiveMaxFileSize 100M ArchiveMaxCompressionRatio 0 #VirusEvent echo virus: %v >> /path/to/file.txt EOF ' sudo chown root:wheel /opt/local/etc/clamd.conf sudo chmod 750 /opt/local/etc/clamd.conf
sudo nano /Library/LaunchDaemons/net.clamav.clamd.plist <?xml version="1.0" encoding="UTF-8"?> DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Disabledkey>/> <key>Labelkey> net.clamav.clamd< /string> <key>ProgramArgumentskey>/opt/local/sbin/clamdstring> -c< /string> <string>/opt/local/etc/clamd.confstring> </array> <key>RunAtLoadkey>/> <key>UserNamekey> root< /string> dict> </plist> sudo chown root:wheel /Library/LaunchDaemons/net.clamav.clamd.plist sudo chmod 0644 /Library/LaunchDaemons/net.clamav.clamd.plist sudo launchctl load -w /Library/LaunchDaemons/net.clamav.clamd.plist #sudo launchctl unload -w /Library/LaunchDaemons/net.clamav.clamd.plist
# create ClamAV directories mkdir -p "$HOME/Documents/ClamAV/Quarantine" mkdir -p "$HOME/Documents/ClamAV/Downloads" # Safari -> Preferences ... -> Save downloaded files to:mkdir -p "$HOME/Documents/ClamAV/EmailAttachments" sudo chown -R $(whoami):wheel "$HOME/Documents/ClamAV" sudo chmod -R 770 "$HOME/Documents/ClamAV" # create a timestamp file touch ~/.clamav_ timestamp sudo chown $(whoami):wheel "$HOME/.clamav_timestamp" sudo chmod 400 "$HOME/.clamav_timestamp" stat -x $HOME/.clamav_timestamp #--------------------------------- # Create a BASH script that will - controlled by ~/Library/LaunchAgents/net.clamav.dirwatcher.plist below - run # a clamdscan or clamscan command on files that have been changed or modified in the specified directories # nano $HOME/Documents/ClamAV/watchdirs.sh #!/bin/bash exec >/dev/console 2>&1 # write stdout & stderr to console.log in /Library/Logs/Console/ echo -e "\n$(/bin/date "+%Y-%m-%d %H:%M:%S %Z"): ... WATCHDIRS.SH for ClamAV ... STARTED ...\n" # All files added to the watched directories during the specified sleep period (in seconds) will be scanned for viruses. # Files added to the directories while a virus scan is being done may not be included in the current virus scan, but # they will get scanned next time a virus scan is scheduled to run which can, for example, be determined by the launch agent # variable StartInterval. Increase the value of the specified sleep period (in seconds) if you expect large files or # directories to be copied or downloaded to the watched directories. /bin/sleep 60 SCANDIR1="$HOME/Documents/ClamAV/Downloads" SCANDIR2="$HOME/Documents/ClamAV/EmailAttachments" QUARANTINEDIR="$HOME/Documents/ClamAV/Quarantine" TOUCHFILE="$HOME/.clamav_timestamp" find=/usr/bin/find clamdscan=/opt/local/bin/clamdscan clamscan=/opt/local/bin/clamscan if [[ ! -e "$TOUCHFILE" ]]; then /usr/bin/touch -afm "$TOUCHFILE" /usr/sbin/chown $(whoami):$(whoami) "$TOUCHFILE" /bin/chmod 400 "$TOUCHFILE" $clamdscan --copy="$QUARANTINEDIR" "$SCANDIR1" || $clamscan -i --copy="$QUARANTINEDIR" -r "$SCANDIR1" $clamdscan --copy="$QUARANTINEDIR" "$SCANDIR2" || $clamscan -i --copy="$QUARANTINEDIR" -r "$SCANDIR2" exit 0 fi timestamp=$(/bin/date "+%Y%m%d%H%M.%S") # store timestamp before starting the virus scan if /bin/ps -ax | /usr/bin/grep clamd | /usr/bin/grep -v grep > /dev/null; then # run clamdscan # scan all files that have been changed or modified after the $TOUCHFILE timestamp of the last virus scan # optional: $find -x "$SCANDIR1" "$SCANDIR2" -type f ... (but mind the 'sysctl kern.argmax' limit for xargs!) # optional: to exclude .DS_Store files add: \! -name ".DS_Store" # alternative: first find changed or modified directories # find -x "$SCANDIR1" "$SCANDIR2" -type d \( -newercm "$TOUCHFILE" -or -newermm "$TOUCHFILE" \) -print0 | while read -d $'\0' scandir; do echo "find -x $scandir -maxdepth 1 -type f ..."; done $find -x "$SCANDIR1" -type f \( -newercm "$TOUCHFILE" -or -newermm "$TOUCHFILE" \) -print0 | xargs -0 $clamdscan --copy="$QUARANTINEDIR" $find -x "$SCANDIR2" -type f \( -newercm "$TOUCHFILE" -or -newermm "$TOUCHFILE" \) -print0 | xargs -0 $clamdscan --copy="$QUARANTINEDIR" else # run clamscan $find -x "$SCANDIR1" -type f \( -newercm "$TOUCHFILE" -or -newermm "$TOUCHFILE" \) -print0 | xargs -0 $clamscan -i --copy="$QUARANTINEDIR" $find -x "$SCANDIR2" -type f \( -newercm "$TOUCHFILE" -or -newermm "$TOUCHFILE" \) -print0 | xargs -0 $clamscan -i --copy="$QUARANTINEDIR" fi # update the $TOUCHFILE timestamp with the pre-scan $timestamp /usr/bin/touch -f -t $timestamp "$TOUCHFILE" echo -e "\n$(/bin/date "+%Y-%m-%d %H:%M:%S %Z"): ... WATCHDIRS.SH for ClamAV ... DONE ...\n" exit 0 #--------------------------------- sudo chown root:wheel ~/Documents/ClamAV/watchdirs.sh sudo chmod 0770 ~/Documents/ClamAV/watchdirs.sh
# nano ~/Library/LaunchAgents/net.clamav.dirwatcher.plist # open -e ~/Library/LaunchAgents/net.clamav.dirwatcher.plist # Note: Don't use $HOME or any other variables in the file paths you have to specify in the .plist files below! # Use the full file paths without any variables! # WatchPaths virus scanner launch agent (combined with StartInterval) # scan the directories specified the same in watchdirs.sh and this .plist file when they are modified or after a specified time interval respectively <?xml version="1.0" encoding="UTF-8"?> DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Disabledkey>/> <key>Labelkey> net.clamav.dirwatcher< /string> <key>LowPriorityIOkey>/> <key>OnDemandkey> /> <key>ProgramArgumentskey> /full/path/to/Documents/ClamAV/watchdirs.shstring> </array> <key>StartIntervalkey> 1800< /integer> <key>WatchPathskey>/full/path/to/Documents/ClamAV/Downloadsstring> /full/path/to/Documents/ClamAV/EmailAttachmentsstring> </array> dict> </plist> #-------------------------------------------------------------------------------- # StartInterval virus scanner launch agent # scan the directories specified in watchdirs.sh at the specified time intervals (given in seconds) <?xml version="1.0" encoding="UTF-8"?> DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Disabledkey> /> <key>Labelkey> net.clamav.dirwatcher< /string> <key>LowPriorityIOkey>/> <key>ProgramArgumentskey> /full/path/to/Documents/ClamAV/watchdirs.shstring> </array> <key>StartIntervalkey> 7200< /integer> dict> </plist> #-------------------------------------------------------------------------------- # StartCalendarInterval virus scanner launch agent # scan the directories specified in watchdirs.sh at the specified times of the day <?xml version="1.0" encoding="UTF-8"?> DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Disabledkey>/> <key>Labelkey> net.clamav.dirwatcher< /string> <key>LowPriorityIOkey>/> <key>ProgramArgumentskey> /full/path/to/Documents/ClamAV/watchdirs.shstring> </array> <key>StartCalendarIntervalkey> /key> <integer>7integer> Hour< Minute< /key> <integer>45integer> </dict> <key>StartCalendarIntervalkey>/key> <integer>12integer> Hour< Minute< /key> <integer>30integer> </dict> dict> </plist> #-------------------------------------------------------------------------------- sudo chown root:wheel ~/Library/LaunchAgents/net.clamav.dirwatcher.plist sudo chmod 0770 ~/Library/LaunchAgents/net.clamav.dirwatcher.plist ls -l ~/Library/LaunchAgents/net.clamav.dirwatcher.plist launchctl load -w ~/Library/LaunchAgents/net.clamav.dirwatcher.plist #launchctl unload -w ~/Library/LaunchAgents/net.clamav.dirwatcher.plist sudo reboot open -a Console # update clamd virus database freshclam; sleep 5; sudo clamd RELOAD
# nano $HOME/Documents/ClamAV/watchdirs.sh #!/bin/bash # check downloaded files or directories in the specified $QueueDirectory for viruses and then move them to $MoveDir # rename the files or folders to be moved to $MoveDir if necessary # remove anything else from the $QueueDirectory exec >/dev/console 2>&1 # write stdout & stderr to console.log in /Library/Logs/Console/ echo -e "\n$(/bin/date "+%Y-%m-%d %H:%M:%S %Z"): ... WATCHDIRS.SH for ClamAV ... STARTED ...\n" /bin/sleep 5 QUARANTINEDIR="$HOME/Documents/ClamAV/Quarantine" TOUCHFILE="$HOME/.clamav_timestamp" QueueDirectory="$HOME/Documents/ClamAV/Downloads/QueueDirectory" # Safari -> Preferences ... -> Save downloaded files to:/bin/mkdir -p "$QueueDirectory" MoveDir="$HOME/Documents/ClamAV/Downloads" /bin/mkdir -p "$MoveDir" find=/usr/bin/find clamdscan=/opt/local/bin/clamdscan clamscan=/opt/local/bin/clamscan if [[ -f "$QueueDirectory"/.DS_Store ]]; then /bin/rm -f "$QueueDirectory"/.DS_Store; fi # alternative to $TOUCHFILE time stamp #/usr/bin/touch ~/Desktop/test.txt #t1=$(/bin/date +%s) #/bin/sleep 1 #/usr/bin/touch -f -am ~/Desktop/test.txt # ... file is being downloaded ... #t2=$(/usr/bin/stat -f %m ~/Desktop/test.txt) #echo $(($t1 - $t2)) #if [[ $t1 -lt $t2 ]]; then echo "file was modified"; else echo "file was not modified"; fi # directory test DirTest="$($find -x "$QueueDirectory" -type d -maxdepth 1 -not -regex "^$QueueDirectory$")" if [[ -n "$DirTest" ]]; then # download is directory $find -x "$QueueDirectory" -type d -maxdepth 1 -not -regex "^$QueueDirectory$" -print0 | while read -d $'\0' dir; do /usr/bin/touch -f -am "$TOUCHFILE" /bin/sleep 3 unset -v file_modified file_modified=0 # check if a file within $dir has been modified while read -d $'\0' file; do # set file_modified to 1 if at least one file has been modified if [[ "$TOUCHFILE" -ot "$file" ]]; then file_modified=1; break; fi done < <($find -x "$dir" -type f -print0 2>/dev/null) if [[ -d "$dir" ]] && [[ "$TOUCHFILE" -nt "$dir" ]] && [[ $file_modified -eq 0 ]]; then $clamdscan --no-summary --copy="$QUARANTINEDIR" "$dir" || $clamscan -i -r --no-summary --copy="$QUARANTINEDIR" "$dir" bname="$(/usr/bin/basename "$dir")" if [[ ! -d "$MoveDir/$bname" ]]; then /bin/mv "$dir" "$MoveDir" else newMoveDir="$MoveDir/$(/bin/date "+%Y-%m-%d-%H%M.%S")-$bname" /bin/mv "$dir" "$newMoveDir" fi fi done else $find -x "$QueueDirectory" -type f -maxdepth 1 -print0 | while read -d $'\0' file; do # download is file /usr/bin/touch -f -am "$TOUCHFILE" /bin/sleep 3 if [[ -f "$file" ]] && [[ "$TOUCHFILE" -nt "$file" ]]; then $clamdscan --no-summary --copy="$QUARANTINEDIR" "$file" || $clamscan -i --no-summary --copy="$QUARANTINEDIR" "$file" # the mv command preserves metadata and resource forks of files on Extended HFS volumes (Mac OS X 10.4) bname="$(/usr/bin/basename "$file")" if [[ ! -f "$MoveDir/$bname" ]]; then /bin/mv "$file" "$MoveDir" else newMoveDir="$MoveDir/$(/bin/date "+%Y-%m-%d-%H%M.%S")-$bname" /bin/mv "$file" "$newMoveDir" fi fi done fi if [[ -f "$QueueDirectory"/.DS_Store ]]; then /bin/rm -f "$QueueDirectory"/.DS_Store; fi $find -x "$QueueDirectory" -not -type f -not -type d -print0 | while read -d $'\0' item; do /bin/rm -f "$item"; done echo -e "\n$(/bin/date "+%Y-%m-%d %H:%M:%S %Z"): ... WATCHDIRS.SH for ClamAV ... DONE ...\n" exit 0 #------------------------------------ # nano ~/Library/LaunchAgents/net.clamav.dirwatcher.plist Disabled Label net.clamav.dirwatcher ProgramArguments /full/path/to/Documents/ClamAV/watchdirs.sh QueueDirectories /full/path/to/Documents/ClamAV/Downloads/QueueDirectory
# set permissions #sudo chown -R root:wheel /opt #sudo chmod -R 755 /opt #sudo chown -R root:wheel /opt/local/share/clamav #sudo chmod -R 0770 /opt/local/share/clamav # bash script to update the clamd virus database # sudo nano /usr/local/sbin/update_clamd_db.sh #!/bin/bash /bin/sleep 120 # write stdout & stderr to console.log exec >/dev/console 2>&1 # check if internet connection is alive and database.clamav.net is reachable /usr/bin/curl -I -L -s --max-time 15 database.clamav.net 1>/dev/null if [[ $(echo $?) -eq 0 ]]; then /opt/local/bin/freshclam -u root /bin/sleep 3 #if [[ -e "/tmp/clamd" ]]; then /bin/rm -f /tmp/clamd; fi #/opt/local/sbin/clamd -c /opt/local/etc/clamd.conf # recreates the local socket file /tmp/clamd as specified in /opt/local/etc/clamd.conf above (/bin/sleep 3; echo RELOAD; /bin/sleep 3; echo "exit") | /usr/bin/telnet -u /tmp/clamd >/dev/null 2>&1 #echo RELOAD | /opt/local/bin/socat - /tmp/clamd # an alternative that requires: sudo port install socat /bin/sleep 3 echo -e "\n$(/bin/date "+%Y-%m-%d %H:%M:%S %Z"): clamd virus database successfully updated\n" exit 0 else echo -e "\n$(/bin/date "+%Y-%m-%d %H:%M:%S %Z"): updating the clamd virus database failed; no internet connection to database.clamav.net established\n" exit 1 fi # set permissions sudo chown root:wheel /usr/local/sbin/update_clamd_db.sh sudo chmod 0770 /usr/local/sbin/update_clamd_db.sh #------------------------ # launchd item to update the clamd virus database using /usr/local/sbin/update_clamd_db.sh # sudo nano /Library/LaunchDaemons/net.clamav.update.clamd.db.plist <?xml version="1.0" encoding="UTF-8"?> DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Disabledkey>/> <key>Labelkey> net.clamav.update.clamd.db< /string> <key>ProgramArgumentskey>/usr/local/sbin/update_clamd_db.shstring> </array> <key>RunAtLoadkey> /> <key>StartIntervalkey> 10800< /integer> <key>UserNamekey>root< /string> <key>GroupNamekey>wheel< /string> dict> </plist> sudo chown root:wheel /Library/LaunchDaemons/net.clamav.update.clamd.db.plist sudo chmod 0644 /Library/LaunchDaemons/net.clamav.update.clamd.db.plist sudo launchctl load -w /Library/LaunchDaemons/net.clamav.update.clamd.db.plist #sudo launchctl unload -w /Library/LaunchDaemons/net.clamav.update.clamd.db.plist sudo reboot # simple shell script syntax check # for more see Debugging Bash scripts, http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_02_03.html bash -n $HOME/Documents/ClamAV/watchdirs.sh bash -n /usr/local/sbin/update_clamd_db.sh # optional: convert XML .plist files to binary format sudo plutil -convert binary1 -- /Library/LaunchDaemons/net.clamav.clamd.plist \ ~/Library/LaunchAgents/net.clamav.dirwatcher.plist \ /Library/LaunchDaemons/net.clamav.update.clamd.db.plist # check .plist file syntax plutil -- /Library/LaunchDaemons/net.clamav.clamd.plist \ ~/Library/LaunchAgents/net.clamav.dirwatcher.plist \ /Library/LaunchDaemons/net.clamav.update.clamd.db.plist # list virus signatures sigtool -l | grep -Ei 'adware|spy' | nl sigtool -l | grep -i phish | nl
# BASH startup files /private/etc/profile # login shell ~/.bash_profile ~/.bash_login ~/.profile /private/etc/bashrc # non-login shell ~/.bashrc # list your BASH startup files ls -a ~ | grep \.bash ls /private/etc | grep -E "bash|profile" # backup the existing BASH startup files sudo cp -p /private/etc/profile /private/etc/profile.orig sudo cp -p /private/etc/bashrc /private/etc/bashrc.orig cp -p ~/.bash_profile ~/.bash_profile.orig cp -p ~/.bash_login ~/.bash_login.orig cp -p ~/.profile ~/.profile.orig cp -p ~/.bashrc ~/.bashrc.orig # /private/etc/profile should contain: # if [[ -f /private/etc/bashrc ]]; then source /private/etc/bashrc; fi sudo sh -c 'echo "if [[ -f /private/etc/bashrc ]]; then source /private/etc/bashrc; fi" >> /private/etc/profile' sudo nano /private/etc/profile # ~/.bash_profile or ~/.bash_login or ~/.profile should contain: # if [[ -f ~/.bashrc ]]; then source ~/.bashrc; fi echo 'if [[ -f ~/.bashrc ]]; then source ~/.bashrc; fi' >> ~/.bash_login nano ~/.bash_login # then add a simple 'echo' command to the existing BASH startup files sudo sh -c 'echo "echo \"... running /private/etc/profile ...\"" >> /private/etc/profile' sudo sh -c 'echo "echo \"... running /private/etc/bashrc ...\"" >> /private/etc/bashrc' echo 'echo "... running ~/.bash_profile ..."' >> ~/.bash_profile echo 'echo "... running ~/.bash_login ..."' >> ~/.bash_login echo 'echo "... running ~/.profile ..."' >> ~/.profile echo 'echo "... running ~/.bashrc ..."' >> ~/.bashrc # check added lines sudo nano /private/etc/profile sudo nano /private/etc/bashrc nano ~/.bash_profile nano ~/.bash_login nano ~/.profile nano ~/.bashrc exit # now relaunch Terminal.app and play around with ... bash echo $SHLVL exec bash echo $SHLVL exec bash -$- exec env -i /bin/bash exec bash --login exec bash -l echo $0 echo $BASH_ENV exec bash -norc bash bash --init-file file bash --rcfile file open-x11 xterm ssh some_other_user@internal_IP_address # cf. http://textsnippets.com/posts/show/1326 ...
# first enable remote login on your admin user account: System Preferences > Sharing > Services > Remote Login # test if remote login is enabled sudo launchctl list | grep com.openssh.sshd # com.openssh.sshd defaults read /System/Library/LaunchDaemons/ssh netstat -an | awk '/\*\.22[[:space:]]+.*LISTEN$/ {print}' # tcp4 ... *.22 ... LISTEN service --test-if-available ssh; echo $? # 0 service --test-if-configured-on ssh; echo $? # 0 # test if sshd daemon supports tcp_wrappers # cf. http://www.la-samhna.de/library/brutessh.html#5 otool -L /usr/sbin/sshd | grep libwrap # then make sure you are connected to the internet ping -c 10 checkip.dyndns.org curl -L -s --max-time 10 http://checkip.dyndns.org | grep -Eo -m 1 '([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}' # then set up the local SOCKS Proxy # cf. http://macapper.com/2007/05/22/advanced-os-x-secure-tunneling-via-ssh #ssh -q -D 8080 -f -C -N -x $(whoami)@$(ipconfig getifaddr $(route -n get default | awk '/interface:/ { print $2 }') 2>/dev/null) #ssh -v -D 8080 -f -C -N -x $(whoami)@$(ipconfig getifaddr $(route -n get default | awk '/interface:/ { print $2 }') 2>/dev/null) ssh -q -D 8080 -f -C -N -x $(whoami)@127.0.0.1 # cf. AllowUsers $(whoami)@127.0.0.1 below # ... enter your user account login password # SSH Without a Password # http://www.csua.berkeley.edu/~ranga/notes/ssh_nopass.html # http://homepage.mac.com/kelleherk/iblog/C1901548470/E20061128145420/index.html # RSA mkdir -p $HOME/.ssh chmod -R 0700 $HOME/.ssh ssh-keygen -t rsa -f $HOME/.ssh/id_rsa -P '' cp -p $HOME/.ssh/id_rsa.pub $HOME/.ssh/authorized_keys2 chmod 0600 $HOME/.ssh/authorized_keys2 srm -v $HOME/.ssh/id_rsa.pub #ls -ld $HOME/.ssh #ls -l $HOME/.ssh/authorized_keys2 # encrypt the known_hosts file ssh-keygen -H -f $HOME/.ssh/known_hosts srm -v $HOME/.ssh/known_hosts.old chmod 0600 $HOME/.ssh/known_hosts # securing SSH # See: # - man sshd_config # - sudo nano /private/etc/sshd_config # - http://switch.richard5.net/2006/09/24/securing-your-ssh-access/ # - http://www.mactech.com/articles/mactech/Vol.21/21.02/Security/index.html # - Mac OS X Security Configuration Guides at http://www.apple.com/server/documentation/ sudo sh -c " echo ' # added Protocol 2 PermitRootLogin no PermitEmptyPasswords no ChallengeResponseAuthentication no PasswordAuthentication no UsePAM no PubkeyAuthentication yes AuthorizedKeysFile $HOME/.ssh/authorized_keys2 #KeepAlive yes MaxAuthTries 3 LoginGraceTime 40 LogLevel INFO # QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG #AllowUsers $(whoami) # add more users if you like: ~" # then open Safari ... open -a Safari # ... and go to: # Safari > Preferences ... > Advanced > Proxies: Change Settings ... # > Select a proxy server to configure: SOCKS Proxy > SOCKS Proxy Server: 127.0.0.1 : 8080 > Apply Now sudo reboot # ... or just restart: System Preferences > Sharing > Services > Remote Login ssh -q -D 8080 -f -C -N -x $(whoami)@127.0.0.1 # should now work without password; cf. man ssh_config for configuring SSH shortcuts # check local SOCKS Proxy setup scutil --proxy # SOCKSProxy : 127.0.0.1, SOCKSEnable : 1, SOCKSPort : 8080 sudo ln -s "/Applications/Utilities/Network Utility.app/Contents/Resources/stroke" /bin/portscan portscan localhost 8000 8100 # Open TCP Port: 8080 http-alt lsof -i :22 -P lsof -i :8080 -P lsof -i TCP -P lsof -U -P # list UNIX domain socket files sudo lsof -U -P netstat -n -f inet #-------------------------- # now you can, for example, test if a website can discover your real internal IP address provided your computer # is behind a DSL router and you have a firewall running (cf. http://textsnippets.com/posts/show/1267) # cf. http://www.auditmypc.com/internal-ip.html # first get your internal IP address ipconfig getifaddr $(route -n get default | awk '/interface:/ { print $2 }') # note: to run the 'real IP' test you first have to enable Plug-ins, Java & JavaScript in Safari # Safari > Preferences ... > Security > Enable plug-ins & Enable Java & Enable JavaScript open -a Safari http://www.auditmypc.com/software_audit.asp (in Terminal.app) or dscl . -list /Users AllowUsers $(whoami)@127.0.0.1 # cf. ssh -q -D 8080 -f -C -N -x $(whoami)@127.0.0.1 above #AllowUsers $(whoami)@$(ipconfig getifaddr $(route -n get default | awk '/interface:/ { print $2 }') 2>/dev/null) # requires internet connection #AllowGroups sshusersgroup # cf. dscl . -list /Groups; groups ' >> /private/etc/sshd_config
# The following BASH command-line instructions assume you have a regular user account # and an admin user account on the same computer! # First, log in to the regular user account regular_user_name="$(whoami)" regular_user_path="$HOME" echo $regular_user_name $regular_user_path # note down the output from the echo command # log out from the regular user account # Then log in to the admin account for the following instructions! # first make sure you are connected to the internet ping -c 10 checkip.dyndns.org curl -L -s --max-time 10 http://checkip.dyndns.org | grep -Eo -m 1 '([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}' # get internal IP address & set regular user account information regular_user_name="...insert information from regular user account above..." regular_user_path="...insert information from regular user account above..." internal_IP_address=$(ipconfig getifaddr $(route -n get default | awk '/interface:/ { print $2 }')) echo $internal_IP_address $regular_user_name $regular_user_path # enable remote login: System Preferences > Sharing > Services > Remote Login # test if remote login is enabled service --test-if-available ssh; echo $? # 0 service --test-if-configured-on ssh; echo $? # 0 # SSH Without a Password # admin user account # RSA mkdir -p $HOME/.ssh chmod -R 0700 $HOME/.ssh ssh-keygen -t rsa -f $HOME/.ssh/id_rsa -P '' cp -p $HOME/.ssh/id_rsa.pub $HOME/.ssh/authorized_keys2 chmod 0600 $HOME/.ssh/authorized_keys2 srm -v $HOME/.ssh/id_rsa.pub ls -ld $HOME/.ssh ls -l $HOME/.ssh # regular user account sudo mkdir -p $regular_user_path/.ssh sudo chmod -R 0700 $regular_user_path/.ssh sudo cp $HOME/.ssh/authorized_keys2 $regular_user_path/.ssh/authorized_keys2 #scp ~/.ssh/authorized_keys2 $regular_user_name@$internal_IP_address:~/.ssh/authorized_keys2 sudo chown -R $regular_user_name:$regular_user_name $regular_user_path/.ssh sudo chmod 0600 $regular_user_path/.ssh/authorized_keys2 sudo ls -l $regular_user_path/.ssh sudo ls -ld $regular_user_path/.ssh # delete all files in ~/.ssh on both user accounts #sudo find $regular_user_path/.ssh -type f -exec srm -fv "{}" \; #find $HOME/.ssh -type f -exec srm -fv "{}" \; # log in to regular user account via SSH # enter admin account login password if prompted ssh -i $HOME/.ssh/id_rsa $regular_user_name@$internal_IP_address exit # encrypt the known_hosts file ssh-keygen -H -f $HOME/.ssh/known_hosts srm -v $HOME/.ssh/known_hosts.old chmod 0600 $HOME/.ssh/known_hosts ssh -i $HOME/.ssh/id_rsa $regular_user_name@$internal_IP_address # test ls exit # securing SSH # man sshd_config # sudo nano /private/etc/sshd_config sudo sh -c " echo ' # added Protocol 2 PermitRootLogin no PermitEmptyPasswords no ChallengeResponseAuthentication no PasswordAuthentication no UsePAM no PubkeyAuthentication yes #AuthorizedKeysFile $regular_user_path/.ssh/authorized_keys2 #KeepAlive yes MaxAuthTries 3 #PermitUserEnvironment yes # requires ~/.ssh/environment file; see man ssh and man sshd_config LoginGraceTime 40 LogLevel INFO # QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG #AllowUsers $(whoami) $regular_user_name AllowUsers $(whoami)@$internal_IP_address $regular_user_name@$internal_IP_address ' >> /private/etc/sshd_config " # set up the local SOCKS Proxy # enter admin account login password if prompted ssh -q -D 8080 -f -C -N -x $regular_user_name@$internal_IP_address open -a Safari # Safari > Preferences ... > Advanced > Proxies: Change Settings ... # > Select a proxy server to configure: SOCKS Proxy > SOCKS Proxy Server: 127.0.0.1 : 8080 > Apply Now # restart sshd: System Preferences > Sharing > Services > Remote Login # check local SOCKS Proxy setup scutil --proxy # SOCKSProxy : 127.0.0.1, SOCKSEnable : 1, SOCKSPort : 8080 portscan localhost 8000 8100 # Open TCP Port: 8080 http-alt ssh -p 22 $regular_user_name@$internal_IP_address ls ssh -l $regular_user_name $internal_IP_address 'echo hello world; whoami; hostname; logname' # test privacy of internal IP address open -a Safari http://www.auditmypc.com/software_audit.asp
# first create a symbolic link sudo ln -s "/Applications/Utilities/Network Utility.app/Contents/Resources/stroke" /bin/portscan # usage: portscan address startPort endPort portscan localhost 1 5000 portscan $(/usr/sbin/ipconfig getifaddr en0 2>/dev/null || /bin/echo localhost) 1 10000
# just put them into your ~/.bash_login # and then: source ~/.bash_login function showall() { /usr/bin/defaults write com.apple.finder AppleShowAllFiles TRUE /bin/sleep 1 /usr/bin/killall Finder return 0 } function shownall() { /usr/bin/defaults write com.apple.finder AppleShowAllFiles FALSE /bin/sleep 1 /usr/bin/killall Finder return 0 }
# pdftotext is a command line program that converts PDF files into text files # first get the pdftotext installer package from http://www.bluem.net/downloads/pdftotext_en/ # pdftotext code written by Glyph & Cog, LLC: http://www.glyphandcog.com/Xpdf.html which pdftotext # /usr/local/bin/pdftotext pdftotext -h pdftotext example.pdf pdftotext example.pdf example.txt pdftotext example.pdf - pdftotext -layout -eol unix -enc UTF-8 /path/to/file.pdf /path/to/file.txt