Thursday, November 22, 2012

Pogoplug: Hidden Folders and Files

Being someone who enjoys using Linux, I decided to play around to see if I can hide folders from the Pogoplug web interface and from other users (this works on files too). To say the least, I wasn't surprised that putting a "." (period) before the name of a file or folder will hide it from prying eyes (e.g. .hiddenfolder or .hiddenfile). It is nothing special; however, be aware that a simple ls -a command will show the hidden files. If you are very concerned about some else seeing something you don't want them to see, then you should use chmod 700 -R on the desired hidden directory and it will recursively change your permissions to rwx------ thereby preventing anyone other than the actual user and root from being able to view the files/folders within that directory.

Notes: If you are having issues with Samba or bftpd, then try chmod 750 -R since it will provide read and execute permissions for the group. Assuming that this was on the home directory, it shouldn't be a problem to use either 700 or 750 permissions; however, feel free to experiment if you so desire to see how secure you can make your Pogoplug.

Friday, November 16, 2012

Pogoplug Wireless Adapter

One of the biggest selling points of getting a Pogoplug, besides being able to hack it's firmware and use it's internal Linux operating system for my own purposes, is the ability to make it wireless. To say the least the wi-fi adapter, which can be purchased directly from the Pogoplug Online Store by clicking here, works great. However, I have been running into issues with it disconnecting when using Samba. As of right now I am awaiting for a new wi-fi adapter (my old one crapped out and is getting replaced) for further testing.

I believe that my backup connection using Home Plug technology may be the culprit due to the fact that FTP transfers between my desktop and the Pogoplug remain stable at a very low speeds (about 280KB per a second). The Home Plug has had in the past crashed my NSLU2's Samba services that resulted in having the  entire machine completely crash (buffer overflow or memory leak???). The only way that resolved that issue was to not use Home Plug adapters with my NSLU2. I am hoping that this is the case and it is not something else. I checked the log files on the Pogoplug for Samba and nothing is out of the ordinary prior to the crash, so it leaves me to question whether it is a memory issue, which shouldn't be an issue thanks to the 512MB swap file, or something else. Either way stay tuned for an update when I get my replacement adapter.

* One note about Home Plug that many are unaware of, is that it is very susceptible to line noise that causes corruption of packets as they travel across the power lines within a building; especially when they share the same outlet with other devices (e.g. computer, lamp, etc).

UPDATE: Its not HomePlug as I had originally thought. Surprisingly the Wi-Fi adapter was the cause of the slow connections for FTP and the crashing of Samba. I average about 2 megabytes per a second (MBps) to almost 4 MBps on some occasions. From further testing, I was able to get the Wi-Fi adapter to average 1MBps from originally ~500KBps by moving it closer to my Wi-Fi router. I find this very odd, even when I used USB 3.0 ports to ensure the adapter was getting enough power, it was still averaged below 1MBps. Now back on Ethernet directly connected to the router, the Pogoplug averages ~2.3MBps, slightly faster than my NSLU2. I think I can tweak it and see if I can get additional performance, but as of right now it is rock solid stable with Samba v3.6 and FTP transactions taking place at the same time.

I am still waiting to get my replacement Wi-Fi adapter and hopefully it will lead to faster transfers over the HomePlug connection.

UPDATE 11/18/2012: Over night the FTP and Samba transfer rates are now roughly 3~4MBps sustained. Apparently the Wi-Fi adapter is not all that great, because of the slow transfer rates. I am uncertain why that is the case, but I am assuming it must by either due to 802.11G or just not that great of an on-board antenna, either way I am glad my Pogoplug is finally out performing my NSLU2.

VBScript: Logon Script w/Arrays

Every now and again someone enhances and/or improves something that someone else had built. On one such occasion I had earned kudos on using an array for adding printers to Windows clients in Active Directory. A serious time saver when it comes to add/removing printers in the script. Anyway here it is and feel free to modify and use it:


'**********************************************************************************
' Set Environment Variables
'*********************************************************************************
Set WSHNetwork = WScript.CreateObject("WScript.Network")
Set WSHShell = WScript.CreateObject("WScript.Shell")

On Error Resume Next

Domain = WSHNetwork.UserDomain
UserName = ""

While UserName = ""
UserName = WSHNetwork.UserName
MyGroups = GetGroups(Domain, UserName)
Wend

'*********************************************************************************
' Main Process:
'*********************************************************************************
GrpMeb UserName
ShowBox

Wscript.Quit

'*********************************************************************************
'Function: GetGroups
'*********************************************************************************
Function GetGroups(Domain, UserName)
Set objUser = GetObject("WinNT://" & Domain & "/" & UserName)
GetGroups=""
For Each objGroup In objUser.Groups
GetGroups=GetGroups & "[" & UCase(objGroup.Name) & "]"
Next
End Function

'********************************************************************************
'Function: InGroup
'********************************************************************************
Function InGroup(strGroup)
InGroup=False
If InStr(MyGroups,"[" & UCase(strGroup) & "]") Then
InGroup=True
End If
End Function

'*********************************************************************************
' MapDrives Subroutine
'*********************************************************************************
Sub MapDrive(sDrive,sShare)
On Error Resume Next
WSHNetwork.RemoveNetworkDrive sDrive, 1, 1
wscript.sleep 1000
Err.Clear
WSHNetwork.MapNetworkDrive sDrive,sShare
End Sub

'********************************************************************************
'Map Drives & Add Printers:
'********************************************************************************
Sub GrpMeb(UNAME)
If INGROUP ("Staff") Then
MapDrive "D:", "\\server\data"
End If

Dim objShell,objNetwork, strLocal, addPrinter, i, Printers

Set objNetwork = CreateObject("WScript.Network")
Set objShell = WScript.CreateObject ("WScript.shell")

Select Case True
Case INGROUP ("User Group1")
Printers = Array("Printer1", "Printer2")
objShell.run "net use U: \\server\Site1\%username%", 0,False

Case INGROUP ("User Group2")
Printers = Array("Printer1", "Printer2")
objShell.run "net use U: \\server\Site2\%username%", 0,False

Case Else

objShell.run "net use U: \\server\Main_Office\%username%", 0,False

'********************************************************************************
'Add Printers for Main Office users based on floor
'********************************************************************************
If Not INGROUP ("Floor1") And INGROUP ("HR") Then
Printers = Array("Printer1 Floor2", "Printer2 Floor2")

Else
Printers = Array("Printer1 Floor1", "Printer2 Floor1")

End IF
END SELECT

'********************************************************************************
'Add Printer Loop
'********************************************************************************
For Each Printer in Printers
objNetwork.AddWindowsPrinterConnection "\\server\" & Printer
Next

Set objShell = Nothing

'********************************************************************************
'Additional Map Drives:
'********************************************************************************
If INGROUP ("Special Project Users") Then
MapDrive "S:", "\\server\special"
End If

If INGROUP ("Apps") Then
MapDrive "A:", "\\server\apps"
End If

End Sub

Thursday, November 15, 2012

VBScript: Get Disabled User Accounts

Another script that I wanted to share with the rest of the world. Please be aware that there is a bug that is preventing the replacing of dates with 1/1/1601 to Null (i.e. empty) when it creates the CSV file. If you can let me know how to fix this, then please feel free to tell me or share it in the comments section below.

'########### ORIGINAL SOURCE ###########################################
' PwdLastChanged.vbs
' ----------------------------------------------------------------------
' Copyright (c) 2003-2010 Richard L. Mueller
' Hilltop Lab web site - http://www.rlmueller.net
'########### ORIGINAL SOURCE ###########################################

'########### Non-Expiring Password Audit ################################
' This script checks for user accounts that are in active directory,    
' whose accounts are disabled. It will display their name, username,
' and the date of their last logon in a CSV file.
'
' History:
' Disabled_Users.vbs v1.0 - 11/15/2012
'
'#######################################################################
Option Explicit
Dim strFilePath, objFSO, objFile, adoConnection, adoCommand
Dim objRootDSE, strDNSDomain, strFilter, strQuery, adoRecordset
Dim strDN, objShell, lngBiasKey, lngBias, strPrncName, strLstLgDt
Dim objDate, k, curDate, curMonth, curDay
Dim strFldr, strFile, strFldrPath 

'Set up date variables
curDate = Date()
'strLstMnth = DateAdd("m",-1,curDate)
'strFldr = curDate '& Right(String(2, "0") & Month(strLstMnth),2) 
strFldr = Year(curDate) & Right(String(2, "0") & Month(curDate),2) 

'Check and see if a folder exists in the X:\mydrive\Disabled_Users\ directory
'using the YYYYMM format using the prior month's two digit number; if not, then create it, else create the
'CSV file using the current date in the European date format YYYYMMDD.
Dim fileSys, crtFldr

'Change the path between the quotes if needed
strFldrPath = "X:\mydrive\Disabled_Users\" & strFldr & "\"

Set fileSys = CreateObject("Scripting.FileSystemObject")

If Not fileSys.FolderExists(strFldrPath) Then
 Set crtFldr = fileSys.CreateFolder(strFldrPath)
End If
 
strFile = Year(curDate) & Right(String(2, "0") & Month(curDate),2) & Right(String(2, "0") & Day(curDate),2)
strFilePath = strFldrPath & strFile & ".csv"

Set objFSO = CreateObject("Scripting.FileSystemObject")

' Open the file for write access.
On Error Resume Next
Set objFile = objFSO.OpenTextFile(strFilePath, 2, True, 0)
If (Err.Number <> 0) Then
    On Error GoTo 0
    Wscript.Echo "File " & strFilePath & " cannot be opened"
    Wscript.Quit(1)
End If
On Error GoTo 0

' Obtain local time zone bias from machine registry.
' This bias changes with Daylight Savings Time.            
Set objShell = CreateObject("Wscript.Shell")
lngBiasKey = objShell.RegRead("HKLM\System\CurrentControlSet\Control\" _
    & "TimeZoneInformation\ActiveTimeBias")
If (UCase(TypeName(lngBiasKey)) = "LONG") Then
    lngBias = lngBiasKey
ElseIf (UCase(TypeName(lngBiasKey)) = "VARIANT()") Then
    lngBias = 0
    For k = 0 To UBound(lngBiasKey)
        lngBias = lngBias + (lngBiasKey(k) * 256^k)
    Next
End If


' Filter to retrieve all user objects. 
' NOTE: The line(s) containing (!sAMAccountName=) is used for filtering out user accounts with
' a specific set of characters, those without the * (asterisk) filters out a specific account.
strFilter = "(&(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=2))"

' Filter to retrieve all computer objects.
' strFilter = "(objectCategory=computer)"

'#################### Setup AD Connection & Create CSV File #############################################
'# The code below creatres the active directory connection and then uses the filter generated earlier.  #
'# From there it creates an LDAP query string and performs the actual enumeration of accounts whose     #
'# passwords never expire, along with their last password change date, username, etc. Once completed it #
'# will write each account into a comma delimited spreadsheet (CSV) file.        #
'########################################################################################################
' Use ADO to search the domain for all users.
Set adoConnection = CreateObject("ADODB.Connection")
Set adoCommand = CreateObject("ADODB.Command")
adoConnection.Provider = "ADsDSOOBject"
adoConnection.Open "Active Directory Provider"
Set adoCommand.ActiveConnection = adoConnection

' Determine the DNS domain from the RootDSE object.
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("DefaultNamingContext") 

strQuery = "<LDAP://" & strDNSDomain & ">;" & strFilter _
    & ";Name,userPrincipalName,lastLogon;subtree"

adoCommand.CommandText = strQuery
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 30
adoCommand.Properties("Cache Results") = False

' Enumerate all users. Write each user's Distinguished Name,
' when they last logon.
objFile.WriteLine "Name,Username,Last Logon Date"
Set adoRecordset = adoCommand.Execute
Do Until adoRecordset.EOF
    strDN = adoRecordset.Fields("Name").Value
 
 If (TypeName(adoRecordset.Fields("lastLogon").Value) = "Object") Then
        Set objDate = adoRecordset.Fields("lastLogon").Value
        strLstLgDt = Integer8Date(objDate, lngBias)
    Else
        strLstLgDt = NULL '#1/1/1601# 'Creates Null entries for dates with 1/1/1601
    End If
 
 strPrncName = adoRecordset.Fields("userPrincipalName").Value
    objFile.WriteLine strDN & "," & strPrncName & "," & strLstLgDt
    adoRecordset.MoveNext 
Loop
adoRecordset.Close

  ' Clean up.
objFile.Close
adoConnection.Close

'Open CSV file automatically after writing to it is completed
dim csvOpen
    set csvOpen = CreateObject("WScript.Shell")
     'csvOpen.Exec(strFilePath)
  csvOpen.Run Chr(34) & strFilePath & Chr(34), 1, false

  'Wscript.Echo "Done"

Function Integer8Date(ByVal objDate, ByVal lngBias)
    ' Function to convert Integer8 (64-bit) value to a date, adjusted for
    ' local time zone bias.
    Dim lngAdjust, lngDate, lngHigh, lngLow
    lngAdjust = lngBias
    lngHigh = objDate.HighPart
    lngLow = objdate.LowPart
    ' Account for error in IADsLargeInteger property methods.
    If (lngLow < 0) Then
        lngHigh = lngHigh + 1
    End If
    If (lngHigh = 0) And (lngLow = 0) Then
        lngAdjust = 0
    End If
    lngDate = #1/1/1601# + (((lngHigh * (2 ^ 32)) _
        + lngLow) / 600000000 - lngAdjust) / 1440
    ' Trap error if lngDate is ridiculously huge.
    On Error Resume Next
    Integer8Date = CDate(lngDate)
    If (Err.Number <> 0) Then
        On Error GoTo 0
        Integer8Date = #1/1/1601#
    End If
    On Error GoTo 0
End Function

VBScript: Password Auditing Accounts w/Non-Expiring Passwords

One of the toughest scripts that I had to ever come up with, was one that would allow someone to audit active users accounts whose passwords never expire. To say the least it took quite a bit of research to get it all squared away and make it work as close as to what I wanted it to do. The script below works very well for anyone wanting to perform password audits with aforementioned criteria; however, there is a bug that prevents the script from being able to replace dates returned with 1/1/1601 in them to Null (i.e. empty). Please feel free to modify this script and use it in your environment.

P.S. - if you can correct the bug, please feel free to post the fix on the comments section below :-)

'########### ORIGINAL SOURCE ###########################################
' PwdLastChanged.vbs
' ----------------------------------------------------------------------
' Copyright (c) 2003-2010 Richard L. Mueller
' Hilltop Lab web site - http://www.rlmueller.net
'########### ORIGINAL SOURCE ###########################################

'########### Non-Expiring Password Audit ################################
' This script checks for user accounts that are in active directory,    
' whose passwords never expire, not disabled, and has not been changed 
' over 90 days.
'
' History:
' PWD_AUDIT.VBS v1.0 - 11/08/2012
' PWD_AUDIT.VBS v1.1 - 11/08/2012 - added folder & file creation handling
' PWD_AUDIT.VBS v1.2 - 11/14/2012 - added last logon for better clarity
' 
'#######################################################################

Option Explicit
Dim strFilePath, objFSO, objFile, adoConnection, adoCommand
Dim objRootDSE, strDNSDomain, strFilter, strQuery, adoRecordset
Dim strDN, objShell, lngBiasKey, lngBias, strPrncName, strLstLgDt
Dim objDate, dtmPwdLastSet, k, curDate, curMonth, curDay
Dim strFldr, strFile, strLstMnth, strFldrPath 

'Set up date variables
curDate = Date()
strLstMnth = DateAdd("m",-1,curDate)
strFldr = Year(curDate) & Right(String(2, "0") & Month(strLstMnth),2) 

'Check and see if a folder exists in the X:\pwd_audit\ directory
'using the YYYYMM format using the prior month's two digit number; if not, then create it, else create the
'CSV file using the current date in the European date format YYYYMMDD.
Dim fileSys, crtFldr

'Change the path between the quotes if needed
strFldrPath = "X:\pwd_audit\" & strFldr & "\"

Set fileSys = CreateObject("Scripting.FileSystemObject")
If Not fileSys.FolderExists(strFldrPath) Then
 Set crtFldr = fileSys.CreateFolder(strFldrPath)
End If
 
strFile = Year(curDate) & Right(String(2, "0") & Month(curDate),2) & Right(String(2, "0") & Day(curDate),2)
strFilePath = strFldrPath & strFile & ".csv"

Set objFSO = CreateObject("Scripting.FileSystemObject")

' Open the file for write access.
On Error Resume Next
Set objFile = objFSO.OpenTextFile(strFilePath, 2, True, 0)
If (Err.Number <> 0) Then
    On Error GoTo 0
    Wscript.Echo "File " & strFilePath & " cannot be opened"
    Wscript.Quit(1)
End If
On Error GoTo 0

' Obtain local time zone bias from machine registry.
' This bias changes with Daylight Savings Time.            
Set objShell = CreateObject("Wscript.Shell")
lngBiasKey = objShell.RegRead("HKLM\System\CurrentControlSet\Control\" _
    & "TimeZoneInformation\ActiveTimeBias")
If (UCase(TypeName(lngBiasKey)) = "LONG") Then
    lngBias = lngBiasKey
ElseIf (UCase(TypeName(lngBiasKey)) = "VARIANT()") Then
    lngBias = 0
    For k = 0 To UBound(lngBiasKey)
        lngBias = lngBias + (lngBiasKey(k) * 256^k)
    Next
End If

'#################### DATE HANDLING & CONVERSTION########################################################
'# The code below first obtains the current date and then subtracts 1 quarter (3 months) from that date #
'# prior to converting it to interger8 format for the filter.           #
'########################################################################################################
Dim oocDate, dtmDateValue, dtmAdjusted, lngSeconds 'Note: oocDate is the Out of Compliance Date variable

'Subtract 1 querter (3 months) from current date
'Note: q = quarter, -1 = how many to subtract, Date() = current date
oocDate = DateAdd("q",-1,curDate) 

dtmDateValue = CDate(oocDate)

' Convert datetime value to UTC.
dtmAdjusted = DateAdd("n", lngBias, dtmDateValue)

' Find number of seconds since 1/1/1601.
lngSeconds = DateDiff("s", #1/1/1601#, dtmAdjusted)

' Convert the number of seconds to a string
' and convert to 100-nanosecond intervals.
Dim str64bit
str64Bit = CStr(lngSeconds) & "0000000"

' Filter to retrieve all user objects. 
' NOTE: The line(s) containing (!sAMAccountName=) is used for filtering out user accounts with
' a specific set of characters, those without the * (asterisk) filters out a specific account.
strFilter = "(&(objectCategory=person)(objectClass=user)(userAccountControl>=65536)(pwdLastSet<=" &_
 str64Bit & ")(!userAccountControl:1.2.840.113556.1.4.803:=2)" &_ 
 "(!sAMAccountName=Default*)(!sAMAccountName=Built-in*))" 

' Filter to retrieve all computer objects.
' strFilter = "(objectCategory=computer)"

'#################### Setup AD Connection & Create CSV File #############################################
'# The code below creates the active directory connection and then uses the filter generated earlier.  #
'# From there it creates an LDAP query string and performs the actual enumeration of accounts whose     #
'# passwords never expire, along with their last password change date, username, etc. Once completed it #
'# will write each account into a comma delimited spreadsheet (CSV) file.        #
'########################################################################################################
' Use ADO to search the domain for all users.
Set adoConnection = CreateObject("ADODB.Connection")
Set adoCommand = CreateObject("ADODB.Command")
adoConnection.Provider = "ADsDSOOBject"
adoConnection.Open "Active Directory Provider"
Set adoCommand.ActiveConnection = adoConnection

' Determine the DNS domain from the RootDSE object.
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("DefaultNamingContext") 

strQuery = "<LDAP://" & strDNSDomain & ">;" & strFilter _
    & ";Name,pwdLastSet,userPrincipalName,lastLogon;subtree"

adoCommand.CommandText = strQuery
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 30
adoCommand.Properties("Cache Results") = False

' Enumerate all users. Write each user's Distinguished Name,
' whether they are allowed to change their password, and when
' they last changed their password to the file.
objFile.WriteLine "Name,Username,Password Last Changed Date,Last Logon Date"
Set adoRecordset = adoCommand.Execute
Do Until adoRecordset.EOF
    strDN = adoRecordset.Fields("Name").Value

    ' The pwdLastSet attribute should always have a value assigned,
    ' but other Integer8 attributes representing dates could be "Null".
    If (TypeName(adoRecordset.Fields("pwdLastSet").Value) = "Object") Then
        Set objDate = adoRecordset.Fields("pwdLastSet").Value
        dtmPwdLastSet = Integer8Date(objDate, lngBias)
    Else
        dtmPwdLastSet = NULL '#1/1/1601# 'Modified to create null or empty
    End If
 
 If (TypeName(adoRecordset.Fields("lastLogon").Value) = "Object") Then
        Set objDate = adoRecordset.Fields("lastLogon").Value
        strLstLgDt = Integer8Date(objDate, lngBias)
    Else
        strLstLgDt = NULL '#1/1/1601# 'Modified to create null or empty
    End If
 
 strPrncName = adoRecordset.Fields("userPrincipalName").Value
 
    objFile.WriteLine strDN & "," & strPrncName & "," & dtmPwdLastSet & "," & strLstLgDt
    adoRecordset.MoveNext 
Loop
adoRecordset.Close

  ' Clean up.
objFile.Close
adoConnection.Close

'Open CSV file automatically after writing to it is completed
dim csvOpen
    set csvOpen = CreateObject("WScript.Shell")
     'csvOpen.Exec(strFilePath)
  csvOpen.Run Chr(34) & strFilePath & Chr(34), 1, false

  'Wscript.Echo "Done"

Function Integer8Date(ByVal objDate, ByVal lngBias)
    ' Function to convert Integer8 (64-bit) value to a date, adjusted for
    ' local time zone bias.
    Dim lngAdjust, lngDate, lngHigh, lngLow
    lngAdjust = lngBias
    lngHigh = objDate.HighPart
    lngLow = objdate.LowPart
    ' Account for error in IADsLargeInteger property methods.
    If (lngLow < 0) Then
        lngHigh = lngHigh + 1
    End If
    If (lngHigh = 0) And (lngLow = 0) Then
        lngAdjust = 0
    End If
    lngDate = #1/1/1601# + (((lngHigh * (2 ^ 32)) _
        + lngLow) / 600000000 - lngAdjust) / 1440
    ' Trap error if lngDate is ridiculously huge.
    On Error Resume Next
    Integer8Date = CDate(lngDate)
    If (Err.Number <> 0) Then
        On Error GoTo 0
        Integer8Date = #1/1/1601#
    End If
    On Error GoTo 0
End Function

Tuesday, November 13, 2012

Pogoplug: Useful Commands

cat /proc/meminfo - displays memory information, including swap file availability and utilization.

/opt/sbin/e2fsck /tmp/.cemnt/sda1 - this command will scan and attempt to correct file system corruption issues on ext2 files systems. Please substitute the correct drive mapping for sda1 (e.g. /tmp/.cemnt/sdb1).
For ext3 (or newer), checkout this link: Repairing Linux ext2 or ext3 File System

fdisk /dev/sda - allows you to create/modify/delete partitions on the specified device (e.g. /dev/sdb)

/opt/sbin/mkfs.ext3 -b 4096 /dev/sda1 - allows you to format the specified device and partition with the ext3 file system (e.g. /dev/sdb1 or /dev/sda2, etc).

Pogoplug: How To Setup An FTP Server

Assuming that you have already performed the instructions to setup the Linux operating system on Pogoplug to accept and install Optware packages (click here if you are unsure), you can now install and setup FTP services on your Pogoplug. Please be aware that FTP is insecure by default due to the fact that it performs authentication and transmission in plain text, meaning it is just as secure as a post card going through the mail. Therefore I would only recommend using this setup if you are only transferring data on your internal network or via a VPN (Virtual Private Network) from your device (e.g. Laptop, Smartphone, etc) to your Pogoplug.

  • Login as root into your Pogoplug via SSH.
  • Type in the following command: /opt/bin/ipkg install bftpd
  •  It will install the BFTPD ftp service on your Pogoplug. From there edit the bftpd.conf file with your favorite text editor (e.g. nano, vi, joe, etc), it can be found in: /opt/etc/bftpd.conf
  • Copy and paste the example config file below, and edit it to match your Pogoplug's configuration:
NOTE: The configuration file below is for setting up a standalone FTP server. It has chroot enabled, basically it prevents someone from browsing out of their FTP folder (e.g. home directory) for security reasons. I also have anonymous login disabled; however, that can be remedied by changing the configuration from no to yes in the example configuration.

UPDATE: changed the following line from "no" to "yes", due to the fact that it prevents files from being overwritten by default:
ALLOWCOMMAND_DELE="yes"

#Configuration file for bftpd.
#The given values are only examples, modify this file for your own needs.

global{
  #If set to no, access is allowed.
  #If set to yes, access is denied without giving a reason.
  #If set to anything else, access is denied giving the content of this
  #variable as a reason.
  DENY_LOGIN="no" 

  #The port number where the daemon should listen (only for daemon mode)
  PORT="21"

  #You can force bftpd to use a specific port range in passive mode.
  #Passive mode means that the client will open data connections
  #and the server stays 'passive'.
  #This option can be very useful with some firewall configurations.
  #Seperate values with "," and define ranges with "-".
  #bftpd will try to bind one of these ports in ascending order as
  #you specify them here.
  #If none of the given ports could be bound, the connection is
  #is refused. If you want to bind any free port in that case, add
  #"0" to the list.
  #PASSIVE_PORTS="10000,12000-12100,13000"
  PASSIVE_PORTS="0"

  #If PORT data connections should be opened from port 20, say yes here. You
  #will probably need this if your server is behind a firewall that restricts
  #outgoing packets from ports higher than 1024. Note that this may be a
  #security hole, as the server can not drop its root privileges completely
  #if you say yes here.
  DATAPORT20="no"

  #The password for the administration commands, encrypted (man mkpasswd).
  ADMIN_PASS="x"

  #With this option, you can put your entire FTP environment into a chroot
  #jail. Apart from security, this offers you the possibility of having
  #virtual users that don't exist in the system.
  #Additionally, you can make some kind of 'file pool' by creating a directory
  #with files which you can symlink from the users' homes (this means setting
  #DO_CHROOT=no in order for the users to be able to access that dir.
  #Note that you need the following files in your initial chroot directory:
  #/etc/passwd, /etc/shadow, /etc/group
  #On GNU systems, you will also need the NSS libraries in /lib.
  #INITIAL_CHROOT="/ftp"

  #The bftpdutmp file enables you to record user logins and logouts in
  #bftpd, which is useful for the administration interface (which is not
  #finished yet). You also need the file to be able to restrict the number
  #of users simultaneously logged on, and so on.
  #Note that the directory in which the file resides must already exist.
  #Set the option to "" if you do not want that. This is discouraged for normal
  #use, but can be helpful if you want to create a boot floppy or something.
  PATH_BFTPDUTMP="/opt/var/run/bftpd/bftpdutmp"

  #This option controls the buffer size while transferring files.
  #If you are on a very fast network (fast meaning 100 Mbit/s or more),
  #you should set this to 64000 or something like that.
  #Transferring from localhost to localhost, I had a transfer speed of
  #approx. 15 MB/s with XFER_BUFSIZE=2048 and a speed of approx. 20 MB/s
  #with XFER_BUFSIZE=64000. You should not set big values for this if you have
  #slow (dialup) clients.
  # This option can also be used to (crudely) throttle back
  # transfer speeds. Setting this to a very low value
  # can slow transfer speeds.
  XFER_BUFSIZE="2048"


  # This variable controls whether the transfer buffer (see above option)
  # should change size as more (or less) clients connect to the server.
  # Setting this option to "yes" will put more work on your CPU, but
  # will avoid chewing up as much bandwidth as more people connect.
  # Setting this option to "no" is easier on the CPU, but may cause
  # your bandwidth to spike.
  CHANGE_BUFSIZE="no"



  # This option allows you to add a delay (in microseconds) to
  # the time between when one piece of data was sent
  # and when the next will be sent. This is to aid in
  # throttling bandwidth and applies to each client. The
  # throttling effects the DATA transfers only (not control
  # connections).
  # A value of zero (0) means there is no added delay.
  # A value of about 500000 (five hundred thousand) should
  # delay for about half a second.
  # These delays should be kept low to avoid triggering
  # data transfer timeouts.
  XFER_DELAY="0"

  # This option determines whether hidden files
  # ( files that start with a "." )
  # will be shown in a directory listing.
  # If this option is set to "yes", the client will be
  # able to see hidden files ONLY if they pass the "-a"
  # option to the list command. For example "ls -a".
  # If this option is set to "no", then hidden files are
  # never shown, regardless of whether "-a" is used.
  # Additionally, if we want the server to always send hidden
  # files to the client, whether they request hidden files or
  # not, set this to "always".
  SHOW_HIDDEN_FILES="yes"

  # This option determines whether files not readable
  # to the ftp user will be shown in a directory listing.
  SHOW_NONREADABLE_FILES="no"

  #When set to yes, this option makes the server allow data connections which
  #don't go to the client who initiated them.
  #This is needed for FXP.
  ALLOW_FXP="no"

  #After how many seconds of idle time should a user be kicked from the server?
  CONTROL_TIMEOUT="300"

  #After how many seconds of idle time should a user be kicked from the server
  #during a file transfer?
  DATA_TIMEOUT="30"

  #Use Ratio if you want the client to send a file before he can get a file.
  #Usage: RATIO=send/receive or RATIO=none. Example: RATIO=2/1 lets the client
  #receive a 1 MB file when he has sent a 2 MB file.
  RATIO="none"

  # Use this option to track bandwidth usage. After each session, the server
  # will log how much data was uploaded and downloaded for each user.
  # This option should point to the directory where the log files will
  # be saved.
  # Each day gets its own log file, to make it easier to rotate logs.
  # Please note, this directory must be created manually.
  # BANDWIDTH="/var/log/bftpd"

  #ROOTDIR specifies the root directory of the client. It defaults to %h
  #(user's home directory). %u is replaced by the user name.
  ROOTDIR="%h"

  #Umask for the files or directories users create.
  UMASK="022"

  #Name of the log file. Say "syslog" to log into syslog.
  #Say "" for no logging.
  LOGFILE="/opt/var/log/bftpd.log"

  #Use %v for version, %h for the server FQDN and %i for the server IP address.
  # Note: If you use the "%h" option and you do an inital CHROOT, then
  # you'll need to copy your /etc/hosts and /etc/host.conf files into
  # the chroot jail.
  HELLO_STRING="bftpd %v at %i ready."

  #The server automatically chdirs to the directory given here after login.
  AUTO_CHDIR="/"

  #Authentication type, values: PAM, PASSWD
  AUTH="PASSWD"

  # The FILE_AUTH varible over-rides the AUTH value. If the FILE_AUTH
  # value is set to something other than an empty string ("")
  # bftpd will search through the pathname given in order
  # to find username/password matches.
  # The format of this file is as shown below:
  # username password group home_folder
  # (for example:)
  # robert secret users /home/robert
  # james moose users /mnt/storage
  #
  # A entry with the password field set to * (star) requires
  # no password. Any password the users enters will be accepted.
  # The following example is for a user with no password.
  # anyone * users /home/ftp
  #FILE_AUTH="/etc/ftpdpassword"


  #Enable this if you want the client's IP address to be resolved to a host
  #name. Note that it increases the overhead and it may not work if your DNS
  #is not configured correctly. Clients without a valid DNS name will take very
  #long to connect.
  RESOLVE_CLIENT_IP="no"

  #Path to the message of the day, seen by all users before login.
  MOTD_GLOBAL="/opt/etc/ftpmotd"

  #Path to the message of the day, seen after login, relative to the root
  #path of the user (see ROOTDIR).
  # Use symbols %u and %h in place of user's username and home directory.
  MOTD_USER="/.ftpmotd"

  #If RESOLVE_UIDS is enabled, in directory lists the user and group names
  #are shown instead of UID/GID. This may slow down directory listings.
  RESOLVE_UIDS="yes"

  #If DO_CHROOT is enabled, a user can not access directories other than his
  #HOMEDIR and its subdirectories. DON'T disable this globally if you don't
  #want to have a security hole!
  DO_CHROOT="yes"
  
  #Enable this to log each login to wtmp.
  LOG_WTMP="yes"

  #If you want bftpd to bind itself to one specific network interface, enter
  #its IP address here. Else enter 'any'. This option only works in standalone
  #mode.
  BIND_TO_ADDR="any"


  # This option allows you to over-ride the IP address Bftpd
  # sends to the client. This may be useful is you are behind
  # a router. If an address is given in this option, it over-rides
  # the LAN IP your PC had. It is recommended you leave this option
  # commented out unless you have a special setup.
  #OVERRIDE_IP="127.0.0.1"
  

  #Path to the ftpusers file. It can contain user names that are denied.
  #If it does not exist, every user can log in. If you don't want this,
  #just put a nonexistent filename here.
  PATH_FTPUSERS="/opt/etc/ftpusers"

  #Enable this if you want to deny any user who has a shell which is not in
  #/etc/shells.
  AUTH_ETCSHELLS="no"

  #With the option ALLOWCOMMAND_XXXX, you can disable the command XXXX.
  #For example, if you don't want any user to delete files, you can do
  #ALLOWCOMMAND_DELE="no"
  #Of course, you can disable it for specific users by writing the appropiate
  #lines into the user structures.
  ALLOWCOMMAND_DELE="yes"
  ALLOWCOMMAND_STOR="yes"
  ALLOWCOMMAND_SITE="no"

  #Files that belong to these groups (comma-separated) are hidden in LIST/NLST.
  HIDE_GROUP=""

  #What message should be used as reply for the QUIT command?
  QUIT_MSG="See you later..."

  #The number of users that can be logged in at the same time.
  #If set to "0", an unlimited users will be able to connect. This is not
  #recommended, as it makes DoS attacks possible, even if the clients are
  #kicked after a short time.
  USERLIMIT_GLOBAL="0"

  #This variable controls how often one user can be logged in at one time.
  #This allows you to have a big connection limit (see above) and nevertheless
  #prevent single users from having a lot of connections.
  #This option may also be useful in a user {} or group {} environment.
  USERLIMIT_SINGLEUSER="0"

  #This variable controls how many users are allowed to connect from the same IP
  #address. This prvents one user (or machine) from taking all of the avail
  #connections.
  #If you want to allow unlimited connections, leave this option as "0".
  USERLIMIT_HOST="0"

  #This option allows you to force files to be compressed
  #on the fly during upload. A ".gz" extension will be given
  #to the file. This should usually be turned off ("no"), but
  #may be useful to servers with smaller storage space.
  #To enable this option set the value to "yes".
  #
  # To use this option, bftpd must be configured using
  # "./configure --enable-libz" _before_ running "make".
  GZ_UPLOAD="no"

  #This option allows you to set whether or not files
  #with the extension .gz should be uncompressed on-the-fly
  #during downloads. This should usually be turned off ("no").
  #To enable this feature, set the value to "yes".
  #
  #To use this option, bftpd must be configured using
  # "./configure --enable-libz" _before_ running "make".
  GZ_DOWNLOAD="no"

  # This option is enabled when the server should run
  # a script before writing to the file system. This should
  # usually be commented out, unless you need to prepare the
  # file system for writing.
  # NOTE: Be careful when using this option and the DO_CHROOT option.
  # The location of the root directory can change when using DO_CHROOT.
  # The current working directory (cwd) is passed to the script you run.
  # PRE_WRITE_SCRIPT="/bin/true"

  # This option is enabled when the server should run
  # a script after writing to the file system. This should
  # usually be commented out, unless you need to do something
  # to the file system after writing.
  # NOTE: Be careful when using this option and the DO_CHROOT option.
  # The location of the root directory can change when using DO_CHROOT.
  # The current working directory (cwd) is passed to the script you run.
  # POST_WRITE_SCRIPT="/bin/false"

  # The GNU C library makes some assumptions about the local time zone
  # when run in a chroot environment. The Bftpd server tries to work
  # around these assumptions to give the correct time. If we are
  # running in an environment which does not require the time zone
  # fix, set TIMEZONE_FIX to "no".
  # TIMEZONE_FIX="no"
}

user ftp {
  #Any password fits.
  ANONYMOUS_USER="no"
  DENY_LOGIN="Anonymous login disabled."
  #ROOTDIR="/path/for/anonymous/user"
}

user anonymous {
  #If the client wants anonymous, ftp is taken instead.
  ALIAS="ftp"
}

user root {
  DENY_LOGIN="Root login not allowed."
}

  • Save the configuration and exit the text editor.
  • Open the rcS configuration file in /etc/init.d/rcS with your favorite text editor and add the following line to the end of you rcS file: /opt/bin/bftpd -d
  • Save and exit the text editor. This will have your Pogoplug automatically start the FTP server every time it reboots.
  • Type in the following command to start your FTP server: /opt/sbin/bftpd -d
  • You should now be able to log into your Pogoplug via FTP using any of the user accounts that exist on your Pogoplug.
Troubleshooting BFTPD:
If you are having problems uploading, downloading, and/or viewing files on your Pogoplug, then it is likely a permissions issue. I would only recommend using ext3 file systems on drives that will be used for storing user home directories and/or data, because Linux doesn't retain the UNIX style permissions on NTFS formatted drives and ext2 file systems are susceptible to file corruption due to power outages. Please checkout the troubleshooting tips on the Samba post to resolve any issues you may be experiencing, as they are virtually identical to the issues that one would experience with any FTP service (e.g. BFTPD, VSFTPD, etc).

Pogoplug: Installing Samba v3.6

Assuming you have read many of the other blogs, wikis, etc out there you will notice that many of them do not take security into consideration, which tends to drive me nuts. They also mention that you will need a swap file to run version 3 of Samba; however, that is not completely true. The fact is, you can run Samba v3 without a swap file (or swap partition) as long as you do not install any other services (e.g. FTP, Apache, etc). I will include instructions on how to make a swap file and add it to your rcS configuration file:

How to create a swap file:

  1. Use SSH and login into your Pogoplug
  2. /opt/bin/ipkg install e2fslibs
  3. dd if=/dev/zero of=/tmp/.cemnt/mnt_sda1/swapfile.img bs=1M count=512 #for a 1GB swapfile, use count=1024
  4. /opt/sbin/mkswap /tmp/.cemnt/mnt_sda1/swapfile.img
  5. /opt/sbin/swapon /tmp/.cemnt/mnt_sda1/swapfile.img
  6. /opt/bin/nano /etc/init.d/rcS
  7. Add the line from step 4 before Samba starts up (if already installed) or at the end, and save the file.
  8. Exit out of nano after saving
A few notes about the swap file:
  • I would highly recommend creating the swap file on an actual hard drive and not on flash memory (aka USB or flash drives), because swap files may prematurely exhaust your flash drive's limited write cycles.
  • 512MB swap file should be more than ample, due to the fact that that the Pogoplug's RAM is only 128MB and having it at 1GB will not provide any additional benefit.
How to install Samba v3.6:
Assuming you are still in the same SSH session, if not reconnect and login as root, please follow these instructions a precisely as you can. I am working on the assumption that you have already formatted your hard drives as ext3 (except for the ext2 system drive that you use to install your Optware packages in /opt); if not then, I would recommend searching for sites with info on how to do that. The reason for ext3 is the journaling feature that helps reduce the risk of data corruption in the event of a power outage. I am also assuming that you have already added users to your your Pogoplug via the adduser command and have configured their home directories to be as such: /tmp/.cemnt/mnt_sda1/user1 in the /etc/passwd file. The reason for this to not only simplify the administration of Samba, but to also increase security to a limited degree. 
  • /opt/bin/ipkg install samba36
  • Once it is installed, you will now have to configure using your favorite text editor, I prefer nano, but feel free to use which ever one you like: /opt/bin/nano /opt/etc/samba/smb.conf
  • You can copy and paste the configuration file below; however, please edit the entries to match your Pogoplug's configuration:
# sample samba 3.0 conf file
[global]
log level = 1
log file = /opt/var/log/samba/log.%m
printcap name = /dev/null
load printers = no
printing = bsd


# CHANGE these settings to match your network/workgroup setup
# ------------------
workgroup = WorkgroupName
server string = ServerName
# netbios name = usbdrive
# your wins server ip address
# wins server = 10.0.0.1
# the networks you want to allow connections from
hosts allow = 127.0.0.1 192.
hosts deny = 0.0.0.0/0
# ------------------

config file=/opt/etc/samba/smb.conf
os level = 8
load printers = no
max log size = 10
security = user
encrypt passwords = yes
smb passwd file = /opt/etc/samba/smbpasswd
socket options = TCP_NODELAY SO_KEEPALIVE SO_SNDBUF=16384 SO_RCVBUF=16384
preferred master = no
local master = yes
dns proxy = no
preserve case = yes
short preserve case = yes
default case = upper
case sensitive = no
mangled names = yes
# null passwords = yes
# username map =
dos filetimes = yes
force directory mode=771
force create mode=660
create mask=771
# map system=yes
map to guest=Bad User
guest account = root
guest ok = no
bind interfaces only = yes
# interfaces = ixp0 lo
winbind use default domain = no

[user1]
path = /tmp/.cemnt/mnt_sda1/user1
valid users = user1
public = no
writable = yes
  • Save the file and exit out of the text editor.
  • Edit the rcS file with your favorite text editor (e.g. /opt/bin/nano /etc/init.d/rcS) and add the following lines in the order as they appear:
sleep 20
mount -o exec,remount /tmp/.cemnt/mnt_sda1
mount /tmp/.cemnt/mnt_sda1 /opt
/opt/sbin/swapon /tmp/.cemnt/mnt_sda1/swapfile.img
/opt/etc/init.d/S08samba start
  • Save the file and exit out of the text editor. This will make sure that your Pogoplug will start your swap file and Samba services every time it boots.
  • to start Samba, just type in the following command: /opt/etc/init.d/S08samba start
  • Add user accounts to Samba that are stated within the smb.conf file by issuing the following command with the corresponding user account name followed by the user's password:  /opt/bin/smbpasswd -a username
Troubleshooting Samba v3.6:
If you are running into problems with your Samba shares, it will likely be due to on of the following issues:
  1. Misconfiguration in the smb.conf file
  2. Failed to use an Ext2 or Ext3 (Recommended) file system for your Samba shares
  3. Failed to apply the proper permissions (remember the configuration above is meant for user security)
  4. If you have problems editing your /etc/init.d/rcS file (e.g. read-only file system) try this command: mount -o remount,rw /
  5. Your drive has data corruption, which can be resolved by logging in as root and running the following command on the affected drive: (ext2) /opt/sbin/e2fsck /tmp/.cemnt/sda1 for (ext3) /opt/sbin/e2fsck -t /tmp/.cemnt/sda1
For problem 1, check your log files and verify that everything is correct. One common mistake is not taking into account that your Pogoplug may have your users shares on  /tmp/.cemnt/mnt_sdb1 instead of sda1. As they say Google is your friend.

For problem 2, you can either search for instructions on how to create an Ext3 partition, or you can connect your drive to your Windows computer and format it with Ext3 using the EaseUS Partition Master Home Edition software, which happens to be free :-)

For problem 3, which happens to be a very common issue. First check your permissions on each user's shared directory (e.g.  /tmp/.cemnt/mnt_sda1/user1) and verify that they have the following permissions, like the example below by peforming ls -l /tmp/.cemnt/mnt_sda1/ command:
drwxr-xr-x    4 user1  1000          4096 Nov 10 12:00 user1

If it says root for the user-id and you do not have at least 700 permissions (e.g. drwxr------), then perform the following commands for each user (you can find the user's group numbers in /etc/passwd):

chmod 700 /tmp/.cemnt/mnt_sda1/user1
chown user1 /tmp/.cemnt/mnt_sda1/user1
chgrp 1000 /tmp/.cemnt/mnt_sda1/user1

Pogoplug: Linux Setup

I have recently purchased a device called a Pogoplug Series 4 and have spent many hours getting this simple device from its default configuration as simple "cloud based" NAS (network attached storage) to a useful Linux machine that is far more valuable. I would recommend following the instructions from Aaron Randall's blog post titled: Customizing your Pogoplug  to setup and configure your Pogoplug (regardless of model) to be able to access and use it's internal Linux operating system.

Please Note: I would recommend not installing Samba v2 that is posted on his blog, due to the fact that it's obsolete and requires some special configuration to be able to upload files greater than 2GB. To get past the 2GB limit, you have to mount your shares using CIFS instead of Samba v2's default SMBFS. I have yet to find good instructions on how to do this and therefore would recommend installing Samba v3.