mnewt-blog
mnewt-blog
MN | Matthew Sojourner Newton
15 posts
Don't wanna be here? Send us removal request.
mnewt-blog · 13 years ago
Text
Reporting Active Directory Logons in PowerShell
![](http://media.tumblr.com/tumblr_mcq7a6UtTZ1qz4cdo.png) ### Background Reporting on AD Logons has always been much more difficult than it should be. Before Windows 2003, there was no central log of logons at all. The `lastLogon` attribute on each user object would seem to do the trick; however, it only records the last logon time on the queried domain controller--it is not synchronized between DC's. Even in Windows 2012, there the central logging attribute, `lastLogonTimeStamp`, is only completely replicated every 14 days. ### Goal So, if you want to find out who has logged today across the domain, or who has logged on in the last hour, you need to do some scripting work. The best tool to do that these days is PowerShell. This first script tallies all users who log on within a 24 hour period and creates two csv files: one with all the users' names and a second called `DailyReport.csv`. Each day it creates a new line in the latter csv file. After a number of days, you can make a pretty picture like the ones here. #### PSLoggedOnToday.ps1 #!powershell.exe # ====================================================================== # PSLoggedOnToday.ps1 # Logs a list of users who logged on during the current day # Created by Matthew Newton # 10.17.2012 # # Queries each Domain Controller in the current domain and compiles a # list of distinguishedName and lastLogon attributes for each user. Then # it outputs only those users who have logged on during the current day # (since midnight) as determined by the local computer. # ====================================================================== # # Heavily based on Richard L. Mueller's PSLastLogon.ps1. # Link: http://www.rlmueller.net/PowerShell/PSLastLogon.txt # And: http://www.rlmueller.net/Last%20Logon.htm # # Richard's header is reproduced below: # # ---------------------------------------------------------------------- # Copyright (c) 2011 Richard L. Mueller # Hilltop Lab web site - http://www.rlmueller.net # Version 1.0 - March 16, 2011 # # This program queries every Domain Controller in the domain to find the # largest (latest) value of the lastLogon attribute for each user. The # last logon dates for each user are converted into local time. The # times are adjusted for daylight savings time, as presently configured. # # You have a royalty-free right to use, modify, reproduce, and # distribute this script file in any way you find useful, provided that # you agree that the copyright owner above has no warranty, obligations, # or liability for such use. Trap {"Error: $_"; Break;} $D = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() $Domain = [ADSI]"LDAP://$D" $Searcher = New-Object System.DirectoryServices.DirectorySearcher $Searcher.PageSize = 200 $Searcher.SearchScope = "subtree" $Searcher.Filter = "(&(objectCategory=person)(objectClass=user))" $Searcher.PropertiesToLoad.Add("distinguishedName") > $Null $Searcher.PropertiesToLoad.Add("lastLogon") > $Null # Create hash table of users and their last logon dates. $arrUsers = @{} # Enumerate all Domain Controllers. ForEach ($DC In $D.DomainControllers) { $Server = $DC.Name $Searcher.SearchRoot = "LDAP://$Server/" + $Domain.distinguishedName $Results = $Searcher.FindAll() ForEach ($Result In $Results) { $DN = $Result.Properties.Item("distinguishedName") $LL = $Result.Properties.Item("lastLogon") If ($LL.Count -eq 0) { $Last = [DateTime]0 } Else { $Last = [DateTime]$LL.Item(0) } If ($Last -eq 0) { $LastLogon = $Last.AddYears(1600) } Else { $LastLogon = $Last.AddYears(1600).ToLocalTime() } If ($LastLogon -gt [DateTime]::Today) { If ($arrUsers.ContainsKey("$DN")) { If ($LastLogon -gt $arrUsers["$DN"]) { $arrUsers["$DN"] = $LastLogon } } Else { $arrUsers.Add("$DN", $LastLogon) } } } } # Output file names $fileName = (Get-Date).ToString("yyyy-MM-dd") + "_" + $arrUsers.Count + ".csv" $reportName = "DailyReport.csv" # Output List of Users to CSV &{ $arrUsers.GetEnumerator() | ForEach { New-Object PSObject -Property @{DN = $_.name; lastLogon = $_.value}} } | Export-CSV $fileName -NoType # Append Total Count to CSV $totalRow = "User Count: " + $arrUsers.Count Add-Content $fileName $totalRow # Output Time and User Count to report CSV $reportRow = """" + (Get-Date).ToString() + """," + $arrUsers.Count Add-Content $reportName $reportRow #### Resulting report: ![](http://media.tumblr.com/tumblr_mcq7bzP9TX1qz4cdo.png) The second script is similar to the first. It tallies all users who log on within a 1 hour period and creates two csv files: one with all the users' names and a second called `HourlyReport.csv`. Each hour it creates a new line in the latter csv file. #### PSLoggedOnLastHour.ps1 #!powershell.exe # ====================================================================== # PSLoggedOnLastHour.ps1 # Logs a list of users who logged on during the current day # Created by Matthew Newton # 10.17.2012 # # Queries each Domain Controller in the current domain and compiles a # list of distinguishedName and lastLogon attributes for each user. Then # it outputs only those users who have logged on during the current hour. # # Heavily based on Richard L. Mueller's PSLastLogon.ps1. # Link: http://www.rlmueller.net/PowerShell/PSLastLogon.txt # And: http://www.rlmueller.net/Last%20Logon.htm # # Richard's header is reproduced below: # # ---------------------------------------------------------------------- # Copyright (c) 2011 Richard L. Mueller # Hilltop Lab web site - http://www.rlmueller.net # Version 1.0 - March 16, 2011 # # This program queries every Domain Controller in the domain to find the # largest (latest) value of the lastLogon attribute for each user. The # last logon dates for each user are converted into local time. The # times are adjusted for daylight savings time, as presently configured. # # You have a royalty-free right to use, modify, reproduce, and # distribute this script file in any way you find useful, provided that # you agree that the copyright owner above has no warranty, obligations, # or liability for such use. Trap {"Error: $_"; Break;} $oneHourAgo = (Get-Date).AddHours(-1) $D = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() $Domain = [ADSI]"LDAP://$D" $Searcher = New-Object System.DirectoryServices.DirectorySearcher $Searcher.PageSize = 200 $Searcher.SearchScope = "subtree" $Searcher.Filter = "(&(objectCategory=person)(objectClass=user))" $Searcher.PropertiesToLoad.Add("distinguishedName") > $Null $Searcher.PropertiesToLoad.Add("lastLogon") > $Null # Create hash table of users and their last logon dates. $arrUsers = @{} # Enumerate all Domain Controllers. ForEach ($DC In $D.DomainControllers) { $Server = $DC.Name $Searcher.SearchRoot = "LDAP://$Server/" + $Domain.distinguishedName $Results = $Searcher.FindAll() ForEach ($Result In $Results) { $DN = $Result.Properties.Item("distinguishedName") $LL = $Result.Properties.Item("lastLogon") If ($LL.Count -eq 0) { $Last = [DateTime]0 } Else { $Last = [DateTime]$LL.Item(0) } If ($Last -eq 0) { $LastLogon = $Last.AddYears(1600) } Else { $LastLogon = $Last.AddYears(1600).ToLocalTime() } If ($LastLogon -gt $oneHourAgo) { If ($arrUsers.ContainsKey("$DN")) { If ($LastLogon -gt $arrUsers["$DN"]) { $arrUsers["$DN"] = $LastLogon } } Else { $arrUsers.Add("$DN", $LastLogon) } } } } # Output file names $fileName = (Get-Date).ToString("yyyy-MM-dd-hh-mm") + "_" + $arrUsers.Count + ".csv" $reportName = "HourlyReport.csv" # Output List of Users to CSV &{ $arrUsers.GetEnumerator() | ForEach { New-Object PSObject -Property @{DN = $_.name; lastLogon = $_.value}} } | Export-CSV $fileName -NoType # Append Total Count to CSV $totalRow = "User Count: " + $arrUsers.Count Add-Content $fileName $totalRow # Output Time and User Count to report CSV $reportRow = """" + (Get-Date).ToString() + """," + $arrUsers.Count Add-Content $reportName $reportRow #### Resulting report: ![](http://media.tumblr.com/tumblr_mcq7blDH0k1qz4cdo.png) Enjoy.
2 notes · View notes
mnewt-blog · 13 years ago
Text
Solution: RDP: The Local Security Authority cannot be contacted
![](http://media.tumblr.com/tumblr_mazepwiftH1qz4cdo.png) ### The Problem I have run into this error a few times in the past. Each time I do, I solve it and forget about it, so that it stymies me for a few minutes the next time I run into it. Hopefully after writing this post I'll remember next time. ### The Error Remote Desktop Connection: An authentication error has occurred. The Local Security Authority cannot be contacted Remote Computer: hostname or ip ### The Reason There are myriad reasons why this could crop up. However, for me it has always been one: #### User must change password on next logon Under many situations (such as when the local computer isn't a member of the remote computer's domain) the Remote Desktop Connection application can't handle the prompt to change a user's password when Network Level Authentication is enabled. ### One step forward, two steps back With previous versions of the RDP protocol, a user was allowed to change their password graphically after signing on. However, NLA has no such provision, at least the way it's implemented in RDC. So, if you have to change your password you are SOL unless you can get to a console. ### Workaround In my case, I was able to sign on to a domain member's console using the VMware vSphere Virtual Machine Console. When I did that, I got a friendly password change screen: ![](http://media.tumblr.com/tumblr_mazem0phW01qz4cdo.png) After setting a new password, subsequent Remote Desktop logons work fine.
0 notes
mnewt-blog · 13 years ago
Text
proxy-toggle.sh
![](http://media.tumblr.com/tumblr_mab1zvlEEm1qz4cdo.png) ##Reason for Being I need to change my proxy settings regularly depending on which network I'm connected to. I initially tried [Proxy Switchy](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&ved=0CCIQFjAA&url=https%3A%2F%2Fchrome.google.com%2Fwebstore%2Fdetail%2Fcaehdcpeofiiigpdhbabniblemipncjj&ei=pDxSUMa4M4zQigLh-IGgAQ&usg=AFQjCNG68edvuAF1w8GAa1G_BM5cAgmeww) but found that it took up too much CPU time. There is no excuse for that in such a simple utility, so I decided to trash it and do things the old fashioned way. ##Method It turns out that it's quite trivial to change proxy settings on OS X: sudo networksetup -setsocksfirewallproxy example: sudo networksetup -setsocksfirewallproxy "Wi-Fi" localhost 1080 Then you turn if off with: sudo networksetup -setsocksfirewallproxystate off ##Script However, I can't be trusted to remember the full commands and arguments so I wrote a tiny script to do it: #!/bin/sh PROXY_INTERFACE="USB Ethernet" PROXY_HOST=localhost PROXY_PORT=1080 if [[ $1 == "on" ]]; then sudo networksetup -setsocksfirewallproxy "$PROXY_INTERFACE" $PROXY_HOST $PROXY_PORT echo "SOCKS proxy enabled" elif [[ $1 == "off" ]]; then sudo networksetup -setsocksfirewallproxystate "$PROXY_INTERFACE" off echo "SOCKS proxy disabled" elif [[ $1 == "status" ]]; then echo "======================================================" echo "Network Services:" echo "======================================================" networksetup -listallnetworkservices echo echo "======================================================" echo "Current SOCKS Proxy Settings:" echo "======================================================" networksetup -getsocksfirewallproxy "$PROXY_INTERFACE" echo else echo "`basename $0` toggles SOCKS proxy settings on OS X" echo echo "Usage: " echo " $ proxy on # turns SOCKS proxy on" echo " $ proxy off # turns SOCKS proxy off" echo " $ proxy status # prints status of proxy settings" echo echo "proxy interface: " $PROXY_INTERFACE echo "proxy host: " $PROXY_HOST echo "proxy port: " $PROXY_PORT echo exit 65 # end process with error to indicate incorrect arguments fi Cheers.
0 notes
mnewt-blog · 13 years ago
Quote
So long as we have enough people in this country willing to fight for their rights, we'll be called a democracy.
ACLU Founder Roger Baldwin
0 notes
mnewt-blog · 13 years ago
Text
Ruby is slow, but it's the same speed as comparable languages
Ruby has a fairly well deserved reputation as a slow language. I tend to think that for its most relevant use cases (running high level programs like [text editors](http://redcareditor.com/) and [web sites](http://basecamp.com/), [etc](http://www.ruby-lang.org/en/documentation/success-stories/)) it doesn't much matter. You could always write your application in C or Java, but who wants to do that if they can help it? In his article, [Ruby is faster than Python, PHP, and Perl](http://www.unlimitednovelty.com/2012/06/ruby-is-faster-than-python-php-and-perl.html), [Tony Arcieri](http://www.blogger.com/profile/05698660503129206682) claims that Ruby is faster than these other languages. He uses this table to illustrate his point: ![](http://media.tumblr.com/tumblr_m9l80ibaIf1qz4cdo.png) Is Ruby really faster though? Not really. It's really effectively the same as these other languages. Check out this graph for some perspective: ![](http://media.tumblr.com/tumblr_m9u8omxgka1qz4cdo.png) see source: http://shootout.alioth.debian.org/u32/which-programming-languages-are-fastest.php I don't consider this an indictment of Ruby. Actually, I see it as a great reason to use it. If I can get the same performance out of Ruby as Python, PHP, or Perl then I am certainly not going to choose Perl. As for Python or PHP, I think the choice is a matter of taste. I personally like the elegant readability of Ruby. It is written more for my brain than for a CPU. And it's not any slower than the more C-like Python and it's proven itself much more malleable than PHP. Good stuff. And as for Rails? I don't think its performance is anything to worry about either: ![](http://media.tumblr.com/tumblr_m9u8q1Tidi1qz4cdo.png) see source: http://blog.curiasolutions.com/the-great-web-framework-shootout/
0 notes
mnewt-blog · 13 years ago
Photo
Tumblr media
I've been customizing my Mac OS X shell a bit today. The cyan above is for the current directory and the purple shows the current git branch, which is why it appears when I change directory to a git repository. ##FIRST: oh-my-zsh I used [oh-my-zsh](https://github.com/robbyrussell/oh-my-zsh) to start, but I didn't like any of the included themes. ##NEXT: thoughtbot/dotfiles The thoughtbot guys have put together a nice [zsh dotfiles setup](https://github.com/thoughtbot/dotfiles). They include a handy little script that symlinks from the dotfiles directory to your .* files themselves, making it easy to link up your dotfiles to a github repository for sharing and copying to additional computers. ##CUSTOMIZING My contribution to all this? I extracted the code the thoughtbot guys used to generate their prompt and made a zsh-theme file out of it: `oh-my-zsh/themes/thoughtbot.zsh-theme:` # adds the current branch name in green git_prompt_info() { ref=$(git symbolic-ref HEAD 2> /dev/null) if [[ -n $ref ]]; then echo "[%{$fg_bold[magenta]%}${ref#refs/heads/}%{$reset_color%}]" fi } # expand functions in the prompt setopt prompt_subst # prompt export PROMPT='$(git_prompt_info)[${SSH_CONNECTION+"%{$fg_bold[green]%}%n@%m:"}%{$fg_bold[blue]%}%1~%{$reset_color%}] ' local return_status="%{$fg[red]%}%(?..✘)%{$reset_color%}" RPROMPT='${return_status}%{$reset_color%}' I added an idea from [Steve Losh](http://stevelosh.com/blog/2010/02/my-extravagant-zsh-prompt/) and from [Aaron Malone](http://blog.munge.net/2011/10/fun-with-zsh-themes/). By the way, I really like those themes as well. I recommend Aaron's version just because it's a little more robust. What theme am I using in the screenshot? Tomorrow Night Eighties from [Chris Kempson's Tomorrow Night Eighties](https://github.com/chriskempson/Tomorrow-Theme) for [iTerm2](http://www.iterm2.com). I'm also using the Tomorrow Theme to highlight the code above. ##My Files You can check out [my dotfiles](https://github.com/mnewt/dotfiles) and [customized oh-my-zsh](https://github.com/mnewt/oh-my-zsh) on my [github](https://github.com/mnewt). Feedback and suggestions welcome.
0 notes
mnewt-blog · 13 years ago
Text
Add Code Syntax Highlighting to any page in "Two" Lines
##Background A while back I wrote a brief post in which I shared some simple code to automatically highlight the syntax of code blocks on a blog, [Code Syntax Highlighting in Tumblr](/post/27497248050/code-syntax-highlighting-in-tumblr). I want to revisit that post for two reasons: 1. I want to more fully explain how all this works 2. I have created a small project called **prettify-wrapper** to handle most of the housekeeping, making for a packaged and streamlined code highlighting solution. ##prettify-wrapper I created a repository on github to house the wrapper code, support code, and accompanying themes. You can link directly to it to use it on your site. Please check it out: http://github.mnewton.com/prettify-wrapper/ ## Why this method? and why google-code-prettify? There are tons posts on this subject but most fall short of ideal. Here is why this method is better: ####It's simple. It involves one cut and paste and virtually no thought. ####Nothing changes on the server. It is completely self-contained in one spot in the html. All the rendering happens client side using javascript. ####You don't have to modify html in your posts. This solution does not require any special tags, CSS, or configuration when you post some code. Just wrap your code in `
` tags like you see below. Blogging platforms do that anyway so for most people they do not need to do anything other than copy and paste to get the job done.
printf("Hello World!");
## The Code If you just want this thing to work, copy and paste this code right before your `
` tag: What? You say that's more than two lines? Well, it's two statements that call upon many more lines of actual code. But it's basically two lines of code that you have to worry about. The rest is all behind the scenes. ##Credits ####The originial google-code-prettify You can check out more about [google-code-prettify here](http://google-code-prettify.googlecode.com/svn/trunk/README.html). ####Inspiration * http://ghoti143.tumblr.com/post/1412901908/google-code-prettify-tumblr-love * http://www.codingthewheel.com/archives/syntax-highlighting-stackoverflow-google-prettify * http://www.avoid.org/?p=78 Feedback and Pull Requests are welcome. You can comment here or interact with the project via github.
7 notes · View notes
mnewt-blog · 13 years ago
Text
Windows Installer Batch Script Revisited
## Recap In a previous post, ["Windows Versioning and UAC Elevation in a Batch Script"](/post/27496719688/windows-versioning-and-uac-elevation-in-a-batch-script), I shared a script I wrote (with the help of some other blogs) in order to install Citrix Single Sign-On (aka Password Manager). It is modular, however, and there are a numer of pieces that could be repurposed for a variety of automated installation applications. Since publishing that post, I have evolved the script noticeably. The biggest changes revolve around my client's changing needs with respect to the specifics of the Citrix Single Sign-On deployment. ## Lessons Learned However, there are a number of things that I learned while writing and revising this script that I think will be useful to those who need to deploy Windows applications across a network. These include: - How to detect Windows versions using just batch script - How to Elevate UAC with a single batch script - How to properly run a batch script with multiple parts from a UNC path - How best to react to installer success, error, and reboot prompts from batch scripts - How to check for installation of a package and install it only if necessary, all from the batch script - How to uninstall a package from a batch script I think that's a sizable percentage of the common problems you find when writing slightly complex install scripts ## Why batch files? There are many systems to deploy applications to Windows computers. You have fancy things like Microsoft System Center Configuration Manager (SCCM) and other tools like VBScript and PowerShell. Only VBScript is ubiquitous across Windows XP and up. When necessary, VBScript is a nice tool; however, it's a lot heavier to develop and would have made this script much longer, without adding anything particularly useful. ## Detect Windows versions First, we need to know what we're working with. We use the `ver` command together with `findstr` (Windows' answer to `grep`) to decide which version of Windows the script is running against: REM =========================================================================== REM Check Windows Version REM =========================================================================== ver | findstr /i "5\.0\." > nul IF %ERRORLEVEL% == 0 goto ver_2000 ver | findstr /i "5\.1\." > nul IF %ERRORLEVEL% == 0 goto ver_XP ver | findstr /i "5\.2\." > nul IF %ERRORLEVEL% == 0 goto ver_2003 ver | findstr /i "6\.0\." > nul IF %ERRORLEVEL% == 0 goto ver_Vista ver | findstr /i "6\.1\." > nul IF %ERRORLEVEL% == 0 goto ver_Win7 goto warn_and_proceed ## Elevate User Account Control (UAC) The crux of this script is handling Windows Vista/7 User Account Control. Since the script could have been run in an un-elevated state, we need to check and if necessary run a new script, since we can't elevate a program once it's already running (that's the whole point of UAC!). The user will receive a UAC prompt at this point if Windows is configured to do so. Yes, there's a little VBScript in there. Use when necessary. REM =========================================================================== REM Elevate credentials REM =========================================================================== :warn_and_proceed echo Cannot determine Windows version, proceeding anyway... :elevate REM Check for permissions >nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system" REM If error flag set, we do not have admin. if '%errorlevel%' NEQ '0' ( echo Requesting administrative privileges... goto UACPrompt ) else ( goto gotAdmin ) :UACPrompt echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs" echo UAC.ShellExecute "%~s0", "", "", "runas", 1 >> "%temp%\getadmin.vbs" "%temp%\getadmin.vbs" REM we are done, exiting recursive call exit /B if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" ) echo We have admin privileges, proceeding... ## Run install commands from the UNC working directory We finally get to the meat of the script. The first line tests whether the package is already installed by querying the registry for its Installer GUID. The rest is just housekeeping. REM =========================================================================== REM Run (privileged) Install Commands REM =========================================================================== :prerequisites echo Installing prerequisites... REM Install vc80_vcredist_x86 if not already installed >nul 2>&1 reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{710f4c1c-cc18-4c49-8cbf-51240c89a1a2} if %ERRORLEVEL% == 0 ( echo. vc80_vcredist_x86 already installed ) else ( echo. Installing vc80_vcredist_x86 start /wait %~dp0vc80_vcredist_x86.exe /q if %ERRORLEVEL% == 0 ( echo. SUCCESS ) else ( if %ERRORLEVEL% == 3010 ( echo. SUCCESS, reboot required set REBOOT_FLAG=1 ) else ( echo. ERROR = %ERRORLEVEL% ) ) ) However, there is one particular part that may throw you off. start /wait %~dp0vc80_vcredist_x86.exe /q What is that `%~dp0` business? This is because the script is meant to be run from a UNC path. Most scripts, when executed, work from the directory where their file is located, or the CWD, depending on how they were launched. When you run a script from `\\server\share` you do not have that luxury. So how do you ensure that you can copy your script anywhere and not have to re-write every reference to every file? Enter `%~dp0`. That prefix tells `command.com` to use the script's own path to find the file. In the case of the above command, it would expand it to: start /wait \\server\share\vc80_vcredist_x86.exe /q Very handy. And odd. But that is the way of batch scripting. Nothing but corner cases. `command.com` must have a lot of corners. ## All together now Finally, here is the complete script for your reference, slicing and dicing. If you use it, it would make me happy for you to let me know, and perhaps even share your modifications here. @ECHO OFF REM =========================================================================== REM =========================================================================== REM Elevated credential install script REM Created by Matt Newton REM 07.17.2012 REM [email protected] REM REM This script checks for Windows OS version and if Vista or 7 is detected REM then it re-runs itself within a VBS wrapper to elevate the credentials. REM It then runs the :install commands, cleans up temp files, and exits. REM =========================================================================== REM =========================================================================== set REBOOT_FLAG=0 REM =========================================================================== REM Check Windows Version REM =========================================================================== ver | findstr /i "5\.0\." > nul IF %ERRORLEVEL% == 0 goto ver_2000 ver | findstr /i "5\.1\." > nul IF %ERRORLEVEL% == 0 goto ver_XP ver | findstr /i "5\.2\." > nul IF %ERRORLEVEL% == 0 goto ver_2003 ver | findstr /i "6\.0\." > nul IF %ERRORLEVEL% == 0 goto ver_Vista ver | findstr /i "6\.1\." > nul IF %ERRORLEVEL% == 0 goto ver_Win7 goto warn_and_proceed :ver_Win7 echo OS Version: Windows 7 goto elevate :ver_Vista echo OS Version: Windows Vista goto elevate REM =========================================================================== REM Elevate credentials REM =========================================================================== :warn_and_proceed echo Cannott determine Windows version, proceeding anyway... :elevate REM Check for permissions >nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system" REM If error flag set, we do not have admin. if '%errorlevel%' NEQ '0' ( echo Requesting administrative privileges... goto UACPrompt ) else ( goto gotAdmin ) :UACPrompt echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs" echo UAC.ShellExecute "%~s0", "", "", "runas", 1 >> "%temp%\getadmin.vbs" "%temp%\getadmin.vbs" REM we are done, exiting recursive call exit /B REM =========================================================================== REM Identify OS Versions REM =========================================================================== :ver_2000 echo OS Version: Windows 2000 goto gotAdmin :ver_XP echo OS Version: Windows XP goto gotAdmin :ver_2003 echo OS Version: Windows 2003 goto gotAdmin :gotAdmin if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" ) echo We have admin privileges, proceeding... :install REM =========================================================================== REM Run (privileged) Install Commands REM =========================================================================== :prerequisites echo Installing prerequisites... REM Install vc80_vcredist_x86 if not already installed >nul 2>&1 reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{710f4c1c-cc18-4c49-8cbf-51240c89a1a2} if %ERRORLEVEL% == 0 ( echo. vc80_vcredist_x86 already installed ) else ( echo. Installing vc80_vcredist_x86 start /wait %~dp0vc80_vcredist_x86.exe /q if %ERRORLEVEL% == 0 ( echo. SUCCESS ) else ( if %ERRORLEVEL% == 3010 ( echo. SUCCESS, reboot required set REBOOT_FLAG=1 ) else ( echo. ERROR = %ERRORLEVEL% ) ) ) REM Install vc90_vcredist_x86 if not already installed >nul 2>&1 reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{1F1C2DFC-2D24-3E06-BCB8-725134ADF989} if %ERRORLEVEL% == 0 ( echo. vc90_vcredist_x86 already installed ) else ( echo. Installing vc90_vcredist_x86 start /wait %~dp0vc90_vcredist_x86.exe /q if %ERRORLEVEL% == 0 ( echo. SUCCESS ) else ( if %ERRORLEVEL% == 3010 ( echo. SUCCESS, reboot required set REBOOT_FLAG=1 ) else ( echo. ERROR = %ERRORLEVEL% ) ) ) REM Install if on Windows 32 bit if %processor_architecture% == x86 ( REM Test if Citrix Receiver is installed >nul 2>&1 dir /s "C:\Program Files\Citrix\receiver.exe" if %ERRORLEVEL% == 0 ( echo. Citrix Receiver already installed ) else ( echo. Installing Citrix Receiver start /wait msiexec /i %~dp0Receiver\RIInstaller.msi /passive /norestart if %ERRORLEVEL% == 0 ( echo. SUCCESS ) else ( if %ERRORLEVEL% == 3010 ( echo. SUCCESS, reboot required set REBOOT_FLAG=1 ) else ( echo. ERROR = %ERRORLEVEL% ) ) ) REM Install SSO Plugin if not already installed >nul 2>&1 dir /s "c:\Program Files\Citrix\JavaBridge.dll" if %ERRORLEVEL% == 0 ( echo SSO Agent x86 may have the wrong modules, uninstalling start /wait msiexec /x {A0C5486E-58A8-48FB-91ED-53881E019700} /passive /norestart if %ERRORLEVEL% == 0 ( echo. SUCCESS ) else ( if %ERRORLEVEL% == 3010 ( echo. SUCCESS, reboot required set REBOOT_FLAG=1 ) else ( echo. ERROR = %ERRORLEVEL% ) ) ) REM %~dp0CitrixSSOPlugin32.exe /silent SYNCPOINTTYPE=FileSyncPath SYNCPOINTLOC=\\server\CITRIXSYNC$ DI_SELECT=1 SSPR_SELECT=1 SERVICEURL="https://server/MPMService/" REM An argument of "/forcerestart" can be added to the end to automatically restart echo Installing Citrix Single Sign-On Plugin 5.0 32 bit start /wait msiexec /i %~dp0SSOPlugin32\SFPDSSOPlugin32.msi /passive /norestart if %ERRORLEVEL% == 0 ( echo. SUCCESS ) else ( if %ERRORLEVEL% == 3010 ( echo. SUCCESS, reboot required set REBOOT_FLAG=1 ) else ( echo. ERROR = %ERRORLEVEL% ) ) ) REM Install if on Windows 64 bit if %processor_architecture% == AMD64 ( echo Installing x64 prerequisites... >nul 2>&1 reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{071c9b48-7c32-4621-a0ac-3f809523288f} if %ERRORLEVEL% == 0 ( echo. vc80_vcredist_x64 already installed ) else ( echo. Installing vc80_vcredist_x64 start /wait %~dp0vc80_vcredist_x64.exe /q if %ERRORLEVEL% == 0 ( echo. SUCCESS ) else ( if %ERRORLEVEL% == 3010 ( echo. SUCCESS, reboot required set REBOOT_FLAG=1 ) else ( echo. ERROR = %ERRORLEVEL% ) ) ) >nul 2>&1 reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{4B6C7001-C7D6-3710-913E-5BC23FCE91E6} if %ERRORLEVEL% == 0 ( echo. vc90_vcredist_x64 already installed ) else ( echo. Installing vc90_vcredist_x64 start /wait %~dp0vc90_vcredist_x64.exe /q if %ERRORLEVEL% == 0 ( echo. SUCCESS ) else ( if %ERRORLEVEL% == 3010 ( echo. SUCCESS, reboot required set REBOOT_FLAG=1 ) else ( echo. ERROR = %ERRORLEVEL% ) ) ) REM Test if Citrix Receiver is installed >nul 2>&1 dir /s "C:\Program Files (x86)\Citrix\receiver.exe" if %ERRORLEVEL% == 0 ( echo. Citrix Receiver already installed ) else ( echo. Installing Citrix Receiver start /wait msiexec /i %~dp0Reciever\RIInstaller.msi /passive /norestart if %ERRORLEVEL% == 0 ( echo. SUCCESS ) else ( if %ERRORLEVEL% == 3010 ( echo. SUCCESS, reboot required set REBOOT_FLAG=1 ) else ( echo. ERROR = %ERRORLEVEL% ) ) ) REM Install SSO Plugin if not already installed >nul 2>&1 dir /s "c:\Program Files (x86)\Citrix\ssoShell.exe" if %ERRORLEVEL% == 0 ( echo SSO Agent x86 is already installed, uninstalling start /wait msiexec /x {FC95142E-AD05-4ECB-9F13-93466D6B5C69} /passive /norestart ) REM %~dp0CitrixSSOPlugin64.exe /silent SYNCPOINTTYPE=FileSyncPath SYNCPOINTLOC=\\server\CITRIXSYNC$ DI_SELECT=1 SSPR_SELECT=1 SERVICEURL="https://server/MPMService/" REM An argument of "/forcerestart" can be added to the end to automatically restart echo Installing Citrix Single Sign-On Plugin 5.0 64 bit start /wait msiexec /i %~dp0\SSOPlugin64\SFPDSSOPlugin64.msi /passive /norestart if %ERRORLEVEL% == 0 ( echo. SUCCESS ) else ( if %ERRORLEVEL% == 3010 ( echo. SUCCESS, reboot required set REBOOT_FLAG=1 ) else ( echo. ERROR = %ERRORLEVEL% ) ) ) echo Installation complete if %REBOOT_FLAG% == 0 ( echo You may need to restart the Citrix SSO Plugin manually echo Please press any key to end the install routine pause exit /B ) else ( echo Please press any key to restart your computer pause shutdown -r -c "Citrix SSO Plugin Install" -t 0 ) ## Credits Once again, thank you Evan Greene. I used [your UAC script](http://sites.google.com/site/eneerge/home/BatchGotAdmin) as a starting point for this one.
1 note · View note
mnewt-blog · 13 years ago
Text
Unrolling Citrix Single Sign-On Plugin
# The Problem The Citrix Single Sign-On Plugin (aka Citrix Password Manager) is a decent way to manage user passwords across a typical, fairly homogeneous Windows Enterprise Environment. It is not given as much love by Citrix as I would like, and it has its quirks. But all password management systems do. Today, though, I found a particulary irksome quirk. There is no way to tell the install routine NOT to install the Java Bridge module, which is used to save and replay passwords in Java applications. Most would not find this a horrible problem, but my client happens to have a Java application that is horribly broken by Citrix's Java Bridge module. So it has to go! Other modules can be easily installed, or not, using command line switches. See Citrix's documentation: [To install the Password Manager agent software silently from a command prompt](http://support.citrix.com/proddocs/topic/passwordmanager/pm-install-agent-to-silent-install.html) You think perhaps there is an install option but it's just not documented? I doubt this. if you comb through the install media, including the XML file (SSOPlugin32Metadata.xml), you will not find any reference at all to the Java module. It appears to be needlessly baked in. How do we engineer around this deficiency? ## Preparation First, I grabbed the CitrixSSOPlugin32.exe from the XenApp 6.5 media. It is a self-contained .exe installer. However, like most .exe installers, it can be easily split up into its constituent parts using 7-zip or RAR. Along with support files and directories, you will find two standard .msi files: one for Citrix Receiver and one for SSO. # Solution: MSI Administrative Install Once I had the raw msi files, the rest is easy and well documented by Microsoft. I create an Administrative Install. msiexec /a "Citrix Single Sign-On.msi" After running the above command, a standard install wizard popped up. I went through it as you would in a manual install until it completed. Once completed, however, I was left with a new directory containing an Administrative Install, with all of the options and parameters I chose during the wizard baked directly into the installation. That's all there is to it. I did, however, think of some alternative solutions if that didn't work. ## Alternative Solution #1 You could use [Microsoft Orca](http://msdn.microsoft.com/en-us/library/windows/desktop/aa370557%28v=vs.85%29.aspx) to rip out the offending section. This is a very brute force way of accomplishing our goal. Simply search for Java in the modules section and delete the reference. ## Alternative Solution #2 Lastly, if none of those options worked my last resort was to simply unlink the JavaBridge.dll: regsvr32.exe /u "C:\Program Files\Citrix\Password Manager\helper\JavaBridge.dll" Thankfully, the administrative install worked perfectly for our case. All of this would be unnecessary, however, if Citrix exposed a transform option to disable that module, just as they do for other modules in the Plugin. Please update your install routines, Citrix! There is a reason MSI files were created and when you gloss over functionality that is baked into the architecture in the first place you hurt yourselves and you hurt your users. Please let me know if any of this helped you out. Cheers.
0 notes
mnewt-blog · 13 years ago
Quote
The mass of men lead lives of quiet desperation. What is called resignation is confirmed desperation.
Henry David Thoreau
0 notes
mnewt-blog · 13 years ago
Quote
One should, each day, try to hear a little song, read a good poem, see a fine picture, and, if it is possible, speak a few reasonable words.
Goethe
0 notes
mnewt-blog · 13 years ago
Text
Web Apps need more powerful security standard
I've been developing a web app that needs access to all sites that a user visits. Somewhat similar to lastpass, it scans pages as the user browses and fills in information in forms when appropriate. ### Currently, the only decent way to make such a thing is to put it in a web browser plugin. But what happens when you're on a work computer, kiosk, or mobile device? You lose the great functionality that you've been accustomed to on your computer. ### You're worse off than before because now your workflow is dependent on this functionality you don't have access to. What we need is a secure way to allow a true web app to *access other websites data on our behalf, directly from the browser*. CORS is not the answer (http://en.wikipedia.org/wiki/Cross-origin_resource_sharing) because it relies on each site giving special permission to the web app. I'm not the only one who thinks so. Here is a quote from Tim Berners-Lee: ### "If I can’t give power to apps, then the web app platform cannot compete with native apps." > The open web platform is a strong contender for apps which you write once run anywhere and end up being a better alternative, or quietly moving out, native apps on all kids of device. > These apps have got to be able to completely act as agents trusted by the user, like for example > - a web browser > - a calendar client > - an IMAP client > and so on, none of these can you currently write as a web app, because of CORS. > As a user when I install an app, I want to be able to give it access to a selection of: > - Program storage, to a limit > - Whether it is permanently available or downloaded or cached for a while > - Access to RAM at runtime, to a limit > - Access to the net, maybe to a bandwidth limit > - CPU time when in background, to a limit > - Ability to access anything on the web > - Access to its own local storage up to a given limit > - Access to shared local storage up to a given limit > - Access to my location, as we currently allow an origin; > - Access video and still camera, and sound > - Access to other sensors such as temp, accelerometer, etc > I want to be able to se where all my resources (including CPU, RAM, 'disk') on my laptop or tablet or phone are being used up, just like I do with music and movies. > I want maybe a couple of default profiles for all the above. > (I'll want to sync its local and shared data storage between all my devices too) > If I can't give power to apps, then the web app platform cannot compete with native apps. > I don't want the value of these setting to be the origin domain name of the script of the app, as that is too high a granularity. > Note that when people talk about installation, they often immediately discuss packaging and manifest formats, which will need to be defined, and for which we might have more than one, but is not the crux of the issue -- the crux is allowing it access to precious and/or sensitive resources. > Tim source: http://lists.w3.org/Archives/Public/public-webapps/2012JanMar/0464.html#start464
0 notes
mnewt-blog · 13 years ago
Quote
Still waters run deep
0 notes
mnewt-blog · 13 years ago
Text
Code Syntax Highlighting in Tumblr
**Edited 08/10/2012: See updated post: [Add Code Syntax Highlighting to any page in “Two” Lines](/post/29164259480/add-code-syntax-highlighting-to-any-page-in-two-lines)** It aggravates me that no blogging platform makes it easy to enable code highlighting. Oh well, at least tumblr makes it easy to edit HTML manually to include code highlighting. I put together the code highlighting on this blog using the following two posts as guidelines: * http://ghoti143.tumblr.com/post/1412901908/google-code-prettify-tumblr-love * http://www.codingthewheel.com/archives/syntax-highlighting-stackoverflow-google-prettify Both of those posts are great, but I'm a minimalist so I want to make the whole process a bit easier. You can highlight all of your code blocks with one block that you can copy and paste into your html file right before the `
` tag: pre.prettyprint { overflow-x: auto; margin: 5px 20px 20px; } function styleCode() { if (typeof disableStyleCode != "undefined") { return; } var a = false; $("pre code").parent().each(function() { if (!$(this).hasClass("prettyprint")) { $(this).addClass("prettyprint"); a = true } }); if (a) { prettyPrint() } } $(function() { styleCode(); });
8 notes · View notes
mnewt-blog · 13 years ago
Text
Windows Versioning and UAC Elevation in a Batch Script
**Edited 07/18/2012: See updated post, [Windows Installer Batch Script Revisited](/post/27511333721/windows-installer-batch-script-revisited)** Recently, I needed to write a script that would install multiple independent components onto Windows XP and Windows 7 machines. The Windows 7 machines would be both 32-bit and 64-bit architectures. The install routine needed to: Determine which Windows version it was running on Elevate UAC (User Account Control) on the Windows 7 machines. Determine which processor architecture it was running on (32 bit or 64 bit) Run other install routines according to the above findings and report on their success Run itself and other routintes from a UNC share It turns out there is no simple way to elevate UAC in a batch file. You have to drop to VBScript. The whole routine is a pain to write in VBScript though, because VBScript is a terrible mess of a language. After some searching, I stumbled across this post with a great script by Evan Greene that I used as a starting point: http://sites.google.com/site/eneerge/home/BatchGotAdmin Thanks Evan! I wrapped some additional code around it to determine OS version and processor architecture. Check it out: @ECHO OFF REM =========================================================================== REM Check Windows Version REM =========================================================================== ver | findstr /i "5\.0\." > nul IF %ERRORLEVEL% == 0 goto ver_2000 ver | findstr /i "5\.1\." > nul IF %ERRORLEVEL% == 0 goto ver_XP ver | findstr /i "5\.2\." > nul IF %ERRORLEVEL% == 0 goto ver_2003 ver | findstr /i "6\.0\." > nul IF %ERRORLEVEL% == 0 goto ver_Vista ver | findstr /i "6\.1\." > nul IF %ERRORLEVEL% == 0 goto ver_Win7 goto warn_and_proceed :ver_Win7 echo OS Version: Windows 7 goto elevate :ver_Vista echo OS Version: Windows Vista goto elevate REM =========================================================================== REM Elevate credentials REM =========================================================================== :elevate REM Check for permissions >nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system" REM If error flag set, we do not have admin. if '%errorlevel%' NEQ '0' ( echo Requesting administrative privileges... goto UACPrompt ) else ( goto gotAdmin ) :UACPrompt echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs" echo UAC.ShellExecute "%~s0", "", "", "runas", 1 >> "%temp%\getadmin.vbs" "%temp%\getadmin.vbs" exit /B :warn_and_proceed echo Cannot determine Windows version, proceeding anyway... :gotAdmin :ver_2000 :ver_XP :ver_2003 if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" ) echo We have admin privileges, proceeding... REM =========================================================================== REM Run privileged commands REM =========================================================================== echo Executing install commands start /wait %~dp0vc80_vcredist_x86.exe /q if %ERRORLEVEL% == 0 ( echo. vc_redist_x86 installed successfully ) else ( echo. ERROR in installing vc_redist_x86 ) if %processor_architecture% == x86 ( echo Installing 32 bit version %~dp0CitrixSSOPlugin32.exe /silent SYNCPOINTTYPE=FileSyncPath SSPR_SELECT=1 if %ERRORLEVEL% == 0 ( echo. Citrix SSO Plugin 32-bit installed successfully ) else ( echo. ERROR in installing Citrix SSO Plugin 32-bit ) ) if %processor_architecture% == AMD64 ( echo Installing 64 bit version %~dp0vc80_vcredist_x64.exe /q if %ERRORLEVEL% == 0 ( echo. vc_redist_x64 installed successfully ) else ( echo. ERROR in installing vc_redist_x64 ) %~dp0CitrixSSOPlugin64.exe /silent SYNCPOINTTYPE=FileSyncPath SSPR_SELECT=1 if %ERRORLEVEL% == 0 ( echo. Citrix SSO Plugin 64-bit installed successfully ) else ( echo. ERROR in installing Citrix SSO Plugin 64-bit ) ) echo Script execution complete echo You may close this window now. pause Hopefully this will help you out.
0 notes