Wednesday, February 25, 2009

VBscript to Find Users in Active Directory with Dial-In VPN Access Permissions

Posted by Brian Bohanon

As a systems administrator, it is not a good feeling when the boss comes to you and says "I need to know every user that has remote access." That is, if you can't get it for him. The script below will audit Active Directory to find users that have the dial-in access permissions enabled. The script will search the current Active Directory domain for users with Dial-In (VPN) RRAS permissions enabled.

To begin with the script opens a connection to the directory for the currently logged in user. Once connected, the script loops through the user accounts in the directory and queries each one to find out if the "msNPAllowDialin" has a value of True. If the script finds a user that meets the requirements, a function is called to find the container of the user object. This function will return the full path of the user object as such:

'OU=sales,DC=fabrikam,DC=com'
Because the output is for a CSV file, there are single quotes around the full path so, when the file is opened with Excel it doesn't see the commas in the container path as delimeters. The user's full name and the container path are written out to a CSV file in the same directory as the script in the format:
First Last, 'OU=sales,DC=fabrikam,DC=com'



Option Explicit
On Error Resume Next

Const ADS_SCOPE_SUBTREE = 2

Dim objConnection, objCommand, objRootDSE
Dim objRecordSet, ou
Dim namingContext, fso, outFile

Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")

objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"

Set objCommand.ActiveConnection = objConnection
Set objRootDSE = getobject("LDAP://RootDSE")

namingContext = objRootDSE.Get("defaultNamingContext")

Set objRootDSE = nothing
Set fso = CreateObject("Scripting.FileSystemObject")
Set outFile = fso.CreateTextFile("RRAS_VPN_Users.txt", True)

objCommand.Properties("Page Size") = 1000
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE
objCommand.CommandText = _ "SELECT Name FROM 'LDAP://" & namingContext & WHERE objectCategory='user' " & "AND msNPAllowDialin = TRUE"

Set objRecordSet = objCommand.Execute

objRecordSet.MoveFirst

Do Until objRecordSet.EOF
ou = getOUByUserName(objRecordSet.Fields("Name").Value)
outFile.WriteLine(objRecordSet.Fields("Name").Value & ",'" & ou & "'")
objRecordSet.MoveNext
Loop

outFile.Close

WScript.Echo "Complete"
WScript.Quit

function getOUByUserName(byval UserName)
DIM namingContext, ldapFilter, ou
DIM cn, cmd, rs
DIM objRootDSE

Set objRootDSE = getobject("LDAP://RootDSE")
namingContext = objRootDSE.Get("defaultNamingContext")

Set objRootDSE = nothing ldapFilter = ";(&(objectCategory=User)(name=" & userName & "))" & ";distinguishedName;subtree"
Set cn = createobject("ADODB.Connection")
Set cmd = createobject("ADODB.Command")

cn.open "Provider=ADsDSOObject;"
cmd.activeconnection = cn
cmd.commandtext = ldapFilter

Set rs = cmd.execute

if rs.eof <> true and rs.bof <> true then
ou = rs(0)
ou = mid(ou,instr(ou,",")+1,len(ou)-instr(ou,","))
getOUByuserName = ou
end if

rs.close
cn.close

end function



Saturday, February 21, 2009

How-to Add LinkedIn Profile Popup on Blogger

Posted by Brian Bohanon

I find the new "profile popup" from LinkedIn to be a very nice addition to blog postings. This adds a LinkedIn icon after your name that pops up a window with your profile information. I wanted to add it to my blog, but I couldn't find any instructions on how to accomplish this with Blogger. As such, I had to figure out how to add this (because I thought it was that cool). Below are the instructions on how to add this functionality to your Blogger site.

To begin, you will need to visit the LinkedIn site to get the JavaScript code for this. There are two pieces of code that are needed to make this little piece of magic work.

First, you will need to get the snippet that goes in the section of your Blogger template. To accomplish this, go to the dashboard, click on the Layout tab, then click the "Edit HTML" link below the tabs. This will provide access to the HTML code that runs your blog site. Find the line in the code that is

</head>

On the line above this, paste the first (of two) line of JavaScript from the LinkedIn profile widgets page. The code that I used is below:

<script type="text/javascript" src="http://www.linkedin.com/js/public-profile/widget-os.js"></script>

Next, you will need to get the "profile" line of code that actually points to your profile. On the LinkedIn site, this code points to "Reid Hoffman". To make this point to your profile, just get the URL for your profile from LinkedIn. You can get this by viewing your public profile and copying and pasting that link into the JavaScript code. Then remove "Reid Hoffman" and the closing anchor tag (</a>) and your link should now look like this:

<a class="'linkedin-profileinsider-popup'" href="http://www.linkedin.com/in/bohanonb">

Now you will need to go to the correct section of your Blogger template (still in the Edit HTML section) to paste this link. This is the part that took a while to find. There is a checkbox at the top of the HTML editor window that reads "Expand Widget Templates". Check this box. Find the line that reads:

<span class='fn'><data:post.author></span>

Once you find this section of code, simply paste your customized link between <span class='fn'> and <data:post.author>. Now type in </a>between </data:post.author> and </span> . The result should be something like this:

<span class='fn'><a class='linkedin-profileinsider-popup' href="http://www.linkedin.com/in/bohanonb"><data:post.author></a></span>

Save the template and it will change all of the previous posts to reflect your new LinkedIn Profile Popup Widget.

If you have any problems getting this to work you can ask your question in the comment section or contact me directly through CrossLoop.

Tuesday, February 17, 2009

Administrators v. Developers: Round 1

Posted by Brian Bohanon

For years, I have been administering the Windows OS and various server products that run on it. Some of these include Exchange, SQL Server, BackupExec, Blackberry Enterprise Server, etc. During this time I have found it necessary, and admittedly a little dangerous, to update these products in a timely fashion. The updates provided by Microsoft are most often security updates, critical updates, and service packs. Now, within this list are some additional products like the .Net framework. The .Net framework also has updates and changes. As with many other programming languages, some properties, methods, and/or built-in classes are either depricated and removed, or the number of arguments are changed, or whatever. Here is the question:

Is it the responsibility of the administrator (the person applying the updates) to know what code the updates will potentially cause problems/changes with?

OR

Is it the responsibility of the developer to be up-to-date on the framework they are using to develop applications with, the changes that are being made to that framework by the company (in this case Microsoft) that provides said framework?

OR

Should the updates not be applied for fear of breaking something, thus potentially leaving gaping security holes in your servers?

In my opinion, it would be the responsibility of the developer to understand when changes are going to be made to the framework. I do believe the administrator holds some responsibility in this scenario, and here they are:

  1. Schedule updates for regular, off-hours intervals
  2. Notify everyone that could potentially be affected by any problems that the updates are being applied
  3. Apply the updates and make sure the services are still working properly
With that said, below is a list of things that I feel the developer should be responsible for:
  1. Be aware of the changes that are coming with the different frameworks that you use to develop (Microsoft is currently up to version 3.5 for the .Net framework)
  2. Be aware of the updates that are going to be released that may affect your work (maybe, subscribing to the MS Update feed, email notification, or just read the site!)
  3. Make the appropriate changes to your code when there is a change to the framework

Thursday, February 12, 2009

VBScript to Update Active Directory User Information

Posted by Brian Bohanon

I used this script to read in a CSV file of user names, address information, telephone number, and email address. The script is based on the following format for the CSV:

  • First name
  • Last name
  • Address 1
  • Address2
  • City
  • State
  • Zip
  • Telephone (no spaces, dashes or other characters)
  • Email address (in the format user@domain.com)
The script combines the first and last names into a single full name, and parses the telephone into a standard format using parentheses and dashes. Once the script has concatenated the user name, it searches through the current RootDSE to find the OU that the user's account is in. This function returns the full LDAP path for the object which is then used to find the object and make the requested changes. The script outputs to the screen any user name that can't be found or returns any other error. To put this into a log file, I simply use the output modifier ">" and the name of the output file.


OPTION Explicit

On Error Resume Next

Const ADS_PROPERTY_UPDATE = 2

DIM username, ou, n, arrStr
DIM strFullName, strAddress1, strAddress2
DIM strCity, strState, strZIP, strPhone, strEmail
DIM strAreaCode, strExchange, strDID, strTelephone
DIM objUser, objFSO, objCSVFile, objConnection, objCommand
Dim objShell, objFile, objNetwork

Set objShell = CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")

'Read CSV
Set objCSVFile = objFSO.OpenTextFile("UserInfo.csv",1)

Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection

'set counter value
n = 0

Do while NOT objCSVFile.AtEndOfStream

 arrStr = split(objCSVFile.ReadLine,",")

 strFullName = arrstr(n) & " " & arrstr(n+1)
 strAddress1 = arrstr(n+2)
 strAddress2 = arrstr(n+3)
 strCity = arrstr(n+4)
 strState = arrstr(n+5)
 strZip = arrstr(n+6)
 strPhone = arrstr(n+7)
 'build a traditional phone number
 strAreaCode = mid(strPhone,1,3)
 strExchange = mid(strPhone,4,3)
 strDID = mid(strPhone,7,4)
 strTelephone = "(" & strAreaCode & ") " & strExchange & "-" & strDID
 strEmail = arrstr(n+8)

 ' Call function to find OU from computer name
 ou = getOUByUserName(strFullName)

 if ou = "" then
  wscript.echo strFullName
 else
  i = 0
  Set objUser = GetObject("LDAP://cn=" & strFullName & "," & ou & "")

  do while i < 1
   If err.number <> 0 then
    wscript.echo "Error: " & strFullName & " " & err.number
   else
    'Set the attribute values
    objUser.Put "streetAddress", strAddress1 & vbCrLf & strAddress2
    objUser.Put "l", strCity
    objUser.Put "st", strState
    objUser.Put "postalCode", strZip
    objUser.Put "telephoneNumber", strTelephone
    objUser.Put "mail", strEmail
    'Set the user info
    objUser.SetInfo
   end if
  i = i + 1
  loop

 end if

n = 0

Loop
objCSVFile.Close

function getOUByUserName(byval UserName)

 DIM namingContext, ldapFilter, ou
 DIM cn, cmd, rs
 DIM objRootDSE

 set objRootDSE = getobject("LDAP://RootDSE")
 namingContext = objRootDSE.Get("defaultNamingContext")
 set objRootDSE = nothing

 ldapFilter = " ">;(&(objectCategory=User)(name=" & userName & "))" & _
 ";distinguishedName;subtree"

 set cn = createobject("ADODB.Connection")
 set cmd = createobject("ADODB.Command")

 cn.open "Provider=ADsDSOObject;"
 cmd.activeconnection = cn
 cmd.commandtext = ldapFilter

 set rs = cmd.execute

 if rs.eof <> true and rs.bof <> true then
  ou = rs(0)
  ou = mid(ou,instr(ou,",")+1,len(ou)-instr(ou,","))
  getOUByuserName = ou

 end if

 rs.close
 cn.close

end function

  © Blogger template 'A Click Apart' by Ourblogtemplates.com 2008

Back to TOP