Mailto in SharePoint String Builder

Bit of a weird, one off sort of thing. I was creating a workflow in SharePoint which would send an email. On this email would be an “Approve” and “Decline” button. The decline button was easy enough to do but the approve button turned out to be a complete pain in the back side.

First of all, I would like to tell you to not use mailto whenever you can. There are better programs out there. Trust me. If anyone knows any really good ones that they standby please feel free to leave a comment.

The mailto syntax is basically this:

mailto:RECIPIENT?cc=CCRECIPIENT&subject=SUBJECT TEXT&body=BODY TEXT

This looks simple enough but once you want to start doing some more complicated features/formatting that would otherwise be quite simple in HTML, become near impossible here. Especially with it being in a SharePoint string builder box.

What I wanted was for there to be three lines of text, two in which got information from the SharePoint form to fill in the information and one for adding text. By the way if you didn’t know, to add a new line you can use “%0d0d“.

That’s: percent sign – zero – delta – zero – delta

This is the final code that I ended up with:

mailto:RECIPIENT@EMAIL.COM?cc=[%Current Item:Created By%]&subject=Approval Authorisation for [%Current Item:Created By%]&body=The remote access request for [%Current Item:Created By%] has been approved by [%Current item:Manager's Name%]%0d%0dThe reason for approval is - [%Current Item:Reason for approval%]%0d%0dPlease specify any limitations below:

Here is a picture just in case you want to see it and below that what the actual email looks like:

String Builder

Email

I would like to add that you will have to change the “Add or Change Lookup” so that it finds the “Display Name”, otherwise the users will show as the default SharePoint format which isn’t as good looking. You can see this below:

Display Name

Hope you enjoyed and found this useful. I may to an entire blog trying to outline the possibilities of using the SharePoint string builder and “Define E-Mail Message” features. Suppose you’ll have to wait and see.

Creating a Dynamically Changing WinForm

This is a fairly simple thing, if you know what you’re doing or if you have done it before. But if, like me, you are at a complete lost and sick of searching only to find half complete or even completely contradictory answers, then this is the guide for you.

My goals for this GUI was to have the form resize IF a tick box was $true (ticked)

First I started off created a blank form with a single checkbox item, you can see this below:

$form = New-Object System.Windows.Forms.Form
$form.Text = "New User Form"
$form.Size = New-Object System.Drawing.Size(500,540)
$form.StartPosition = "CenterScreen"
$form.FormBorderStyle = "Fixed3D"
$form.MaximizeBox = $false
$form.MinimizeBox = $false

$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Point(165,470)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"
$OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $OKButton
$form.Controls.Add($OKButton)

$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Point(245,470)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = "Cancel"
$CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $CancelButton
$form.Controls.Add($CancelButton)

$checkbox = New-Object System.Windows.Forms.CheckBox
$checkbox.Location = New-Object System.Drawing.Point(100,100)
$checkbox.Size = New-Object System.Drawing.Size(100,25)
$checkbox.Text = "Test Checkbox"
$form.controls.Add($checkbox)

$result = $form.ShowDialog()

That will create an empty form like the one below:

Initial Form

Now I will add the following code after all the objects but before the end $result variable which displays the form:

$checkbox.add_checkstatechanged({

 if ($checkbox.Checked -eq $True){

  $form.size = new-object system.drawing.size(800,540)

 }else{

  $form.size = new-object system.drawing.size(500,540)

}

})

 

this is the part that will make the form larger if the checkbox is checked and return it to the original size if it isn’t checked. You can do SO many other things as well. For example, having a textbox enabled or disabled, changing the forms title, changing the colour of the form and to be honest just about anything you can think of.

This is the complete script you will need:

$form = New-Object System.Windows.Forms.Form
$form.Text = "New User Form"
$form.Size = New-Object System.Drawing.Size(500,540)
$form.StartPosition = "CenterScreen"
$form.FormBorderStyle = "Fixed3D"
$form.MaximizeBox = $false
$form.MinimizeBox = $false

$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Point(165,470)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"
$OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $OKButton
$form.Controls.Add($OKButton)
$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Point(245,470)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = "Cancel"
$CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $CancelButton
$form.Controls.Add($CancelButton)

$checkbox = New-Object System.Windows.Forms.CheckBox
$checkbox.Location = New-Object System.Drawing.Point(100,100)
$checkbox.Size = New-Object System.Drawing.Size(100,25)
$checkbox.Text = "Test Checkbox"
$form.controls.Add($checkbox)

$checkbox.add_checkstatechanged({
 if ($checkbox.Checked -eq $true){
  $form.Size = New-Object System.Drawing.Size(800,540)
 }else{
  $form.Size = New-Object System.Drawing.Size(500,540)
 }
})

$result = $form.ShowDialog()

This script will create a form like in the screenshots below. In this screenshot the checkbox is not ticked:

Initial Form

And in this screenshot the checkbox has been ticked, making the form size noticeably wider:

Ticked Form

Hope this helps someone struggling with getting started with some of the more complex WinForm tricks. Enjoy and comment if you need any help!

 

 

 

 

Installing And Using Samba Shares On Linux

To install samba capabilities on your Linx box, run the following commands:

sudo apt-get install samba samba-common-bin

This will run off an install process, note that it may ask you if you’re sure about installing this, press y to accept and continue.

Now edit the samba configuration file using:

sudo nano /etc/samba/smb.conf

Go all the way to the end of the file and add the following lines…

  • [share]
  • comment=Pi Share
  • path= DIRECTORY LOCATION e.g. /mnt/library
  • browseable = yes
  • writeable = yes
  • only guest = no
  • create mask = 0777
  • public = no
  • guest ok = no

 

At this point your may need to restart the smb service using the following command:

sudo service smbd restart

You may need to know the IP address of the Linux share in order to access it, you can do this by using “ifconfig” and looking for something along the lines of “192.168…” on the eth0 interface”

To access the share using the Windows and R key to bring up the run dialog box and type in the IP address of the Linux box or its hostname. It would now ask you for credentials, here you should use your regular Linux credentials.

You can see this below:

Credentials Prompt

Once it has accepted my credentials I get the following:

Samba Share

Hopefully, you get the same as I did, if not then leave a comment. Enjoy!

 

Better Credentials Checking in PowerShell

This is something that I have recently created so that when a script asks for a credentials and there is an error, it doesn’t display a big, ugly and often intimidating error message for any poor soul trying to run my scripts.

That’s why I have recently (as in yesterday) “created” a “fool proof” way of entering and validating credentials against a domain.

This was a problem because whenever someone ran my script and did ANYTHING other than enter perfectly correct credentials, it would throw and error and exit the script. Or even carry on with the script WITHOUT THE CREDENTIALS, which obviously wouldn’t work. I know, I know. Amateur hour! But it was a crap system I must admit.

That’d why I spent and hour or so creating this beauty! It captures any errors, such as null credentials and incorrect credentials and only continues if a user exists with the same samaccountname as the one entered at the credentials prompt and if the user is in the domain admins group. Just for added “security”. Really I just want the appropriate people to be using the script.

This is the code I use!

#PROMPTING FOR CREDENTIALS
$cred = $host.UI.PromptForCredential("Need credentials", "Please enter your username and password.", "", "")
if ($cred -ne $null -and $cred -ne ''){
 #CHECKING IF THE CREDENTIAL USERNAME EXISTS
 $check = $(try {Get-ADUser -Identity $cred.UserName} catch {$null})

  if ($check -ne $null){
  #GETTING CREDENTIAL USERNAME GROUPMEMBERSHIP
  $checkadmin = Get-ADPrincipalGroupMembership -Identity $cred.UserName
  $checkadminrefined = $checkadmin.SamAccountName
  #PUTTING GROUP MEMBERSHIP INTO AN ARRAY
  $array = $checkadminrefined
  #CHECKING IF USER GROUP LIST CONTAINS DOMAIN ADMINS
  if ($array -contains "Domain Admins"){
   Write-Host "Credentials are GOOD! - Continuing with script" -ForegroundColor Green
   Start-Sleep -Seconds 1
  }else{
   #RESULT IF USER IS NOT DOMAIN ADMINS
   Clear-Host
   Write-Host "Credentials are not a domain admin! - Close and start again" -ForegroundColor Red ;
   $x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
   Exit
  }
 }else{
  #RESULT IF NO USER CAN BE FOUND FROM CREDENTIAL USERNAME
  Clear-Host
  Write-Host "Check is empty - No user found matching credentials supplied! - Close and start again" -ForegroundColor Red
  $x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
  Exit
 }
}else{
 #RESULT IF PROMPT IS CLOSED / NO CREDENTIALS SUPPLIED
 Clear-Host
 write-host "No credentials supplied - Close and start again" -ForegroundColor Red
 $x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
 Exit
}

You should be able to read the script and see which each part does. I left comments in the script which I don’t normally do since it might be easier for you to see what its doing with pointers at each stage.

Enjoy!

Securely Installing and Using FTP on Linux

First, install VSFTP (Very Secure File Transfer Protocol) using the following command:

sudo apt-get install vsftpd

Now edit the vsftpd.conf file to perfect the setup of VSFTP

open the file using:

sudo nano /etc/vsftpd.conf

You should be shown something similar to below:

vsftpd.conf

Make the following changes to the configuration file…

  • anonymous_enable=NO
  • local_enable=YES
  • write_enable=YES
  • chroot_local_users=YES

now add the following lines to the bottom of the file…

  • force_dot_files=YES
  • allow_writable_chroot=YES

 

Now restart the vsftpd service using:

sudo service vsftpd restart

You should now be able to connect to you Linux box using a program such as FileZilla using your username and password. You may need to get the IP address of your Linux box before you know where to connect to. So on your Linux use the command:

ifconfig

to know where to connect to.

You will notice that you cant move out of your home directory. I have this setup fo security reasons but if you wish to remove this then simply comment out the chroot_local_users part of the vsftpd.conf file.

I will be showing in a future blog how to upload files to external drives whilst chrooted in your home directory. Chrooted helps with security as it means that even if someone gets your username and password, they still cant browse the entire system.

Enjoy!

Making External VFAT Drive Writable on Linux

 

Prerequisites: 

I would install nano, this is a text editor on Linux which is MUCH easier to use for beginners than vi. You can do this by using “sudo apt-get install nano” or “yum install nano” depending on your distribution of Linux.


First we will need to find where in /dev your drive is being displayed. You can do this by running:

lsblk

which will display all the drives currently connected to your Linux machine. The easiest way to see which drive you want is to check the size of the drive. For example, I have connected a 500GB hard drive so when I run “lsblk” I get the following:

lsblk

From this screenshot you can already see that I have mounted the drive partition I require, which in my case is sda3.

Now you need to create a directory in the mnt directory as this is were you should mount drive in Linux to keep things tidy. You can do this by using:

sudo mkdir /mnt/library

I have called by directory “library” but you can call it whatever you want.

Now we need to configure this in the fstab file which basically tells the system what to do with connected drives once the system starts.

You can open the fstab file by using:

sudo nano /etc/fstab

This should give you something similar to below:

fstab 1

Now go to the bottom of the file and add something similar to the one I have added, you can see this below:

fstab

Just for reference the line I have added is:

“/dev/sda3         /mnt/library          vfat          users,umask=00          0          0”

Make sure to check the directory locations as you might have called your something else and your drive label might be different.

You can now check in your /mnt/library directory and you should see that your drive has been mounted and you can delete and add new files to the location.

Enjoy!

Create, Store & Use Encrypted Passwords With PowerShell

This is just a neat little “tactic” I use when I need to connect to the same machine over and over again but don’t want to drive myself insane with having to constantly enter the same username and password. For example, when testing a script.

First you need to enter your password, in plain text, into this script so that it can get the password. This a perfectly safe as it will only be at this point where the password is in plain text.

$password = "PUT PASSWORD HERE" | ConvertTo-SecureString -AsPlainText -Force

This gets the password that you just entered and encrypts it and also puts it into the variable “password”

Now you need to convert the password to an encrypted string of characters using the below command:

$Password2 = $password | ConvertFrom-SecureString | Out-File "PATH TO TEXT FILE TO STORE PASSWORD"

This puts the encrypted password into the text file for later use.

Now, whenever you need to connect to a machine, you can put this into a variable along with the username. Then put them together into a credential and away you go:

$Username = "DOMAIN\username"

$EcryptedPassword = Get-Content "LOCATION TO TEXT FILE" | ConvertTo-SecureString

$Credential = New-Object System.Management.Automation.PSCredential($Username, $EncryptedPassword)

This builds the credential which you can now use with something similar to below:

Invoke-Command -Credential $Credential -ScriptBlock {echo "test"} -ComputerName "COMPNAME" -Authentication CredCSSP

Enjoy!

Resetting pwdLastReset Attribute in Active Directory

This sort of thing is useful if you have a bunch of users that have passwords which are set to not expired, but then you decide that they do need to expire. But if you simply untick the “Password doesn’t expired” attribute then it will instantly make them change their password because the “pwdLastSet” date will be from when the user was first set-up.

This trick will set the “pwdLastSet” date to today so that they have some warning before being told to reset their password.

First of all, make sure that you have “Advanced Features” turned on from the “View” menu.

Now find the user that you want to reset the value for and edit their properties. Navigate to the “Attribute Editor” tab and scroll down until you see the “pwdLastSet” attribute.

Edit the value to be “0“, this means that the value has never been set. See screenshot below.

Changed to 0

Now click okay on all of the boxes until the users properties window has closed. Now reopen the users window, go back to the attributes editor and change pwdLastSet to “-1. See screenshot below:

Changed to -1

Now press okay to all the boxes until the users properties window has closed. Now when you check for the pwdLastSet attribute it will be set to the current date.

Hope this helped you, enjoy!

Linux New Users Form

Following on from my recent upload on Linux scripting, I have yet again created a BASH script to make my Linux’ing life easier. This is also my second script created in BASH so I guess i’ve accomplished something by not running for the hills…

What I needed was a script to make creating FTP users easier on my CentOS box. Below is a list of things I needed the script to accomplish:

  • Get a username from a user prompt
  • Get a Description from a user prompt
  • Create the new user
  • Change the users password
  • Add the username to /etc/vsftpd.userlist
  • Add the username to /etc/vsftpd/chroot_list
  • Make a directory in the home folder of the user called “ftp”
  • Change the permissions and ownership on this directory
  • Make a directory in the “ftp” folder called “files”
  • Change the permissions and ownership on this directory
  • Ask the user to create a share or not
  • Get a share name from user prompt
  • Make a directory in the users “files” folder with the same name as the share name
  • Mount the share to the “files” directory
  • Ask if the new user is the owner of the share
    • if so then change the ownershipa and permissions on the share
    • if not then just change the permissions on the share
  • Finish

Here is my script for achieving these goals:

#!/bin/bash
#Creating new FTP users

##Gathering Variables
echo "Enter a username"
read Username

echo "Enter a description"
read Description

useradd -m -c "$Description" -s /bin/bash $Username

passwd $Username

echo "$Username" | tee -a /etc/vsftpd.userlist
echo "$Username" | tee -a /etc/vsftpd/chroot_list

mkdir /home/$Username/ftp
chown nobody:nobody /home/$Username/ftp
chmod a-w /home/$Username/ftp

mkdir /home/$Username/ftp/files
chown $Username:$Username /home/$Username/ftp/files
chmod 0700 /home/$Username/ftp/files

read -p "Create a share? [yn]: " CreateShare
if [[ $CreateShare = y ]] ; then

 read -p "Enter a share name: " ShareName

 mkdir /home/$Username/ftp/files/$ShareName
 mkdir /home/shares/$ShareName
 mount --bind /home/shares/$ShareName /home/$Username/ftp/files/$ShareName
elif [[ $CreateShare = n ]] ; then
 read -p "Enter the pre-existing share name: " ShareName
 mkdir /home/$Username/ftp/files/$ShareName
 if [ -d /home/shares/$ShareName ] ; then
  echo "Mounting share"
  mount --bind /home/shares/$ShareName /home/$Username/ftp/files/$ShareName
 else
  echo "Cannot find the share name : $ShareName"
 fi
else
 echo "Not a y or n"
fi

read -p "Is $Username the owner of this share? [yn]: " ShareOwner
if [[ $ShareOwner = y ]] ; then
 chown $Username:$Username /home/shares/$ShareName
 chmod 0775 /home/shares/$ShareName
else
 echo "$Username is not the owner of $ShareName"
 chmod 0775 /home/shares/$ShareName
fi

echo "Finished creating user : $Username" * Insert your code here

Hopefully somebody gains something from this, probably not though. Enjoy!

Linux Mounting Script

Recently I have set up a VSFTPD CentOS 7 server and chrooted all the local users to their home directory. *If you know what that means $YourPoints = $YourPoints + 5*

But when ever the system was rebooted or for any other reason that I don’t fully understand yet, the mounts from the shares to the users home directory would get lost. Because the users were chrooted into their home directories, I couldn’t use symbolic or hard links. Instead I had to use the:

mount --bind

option to make the mount accessible to the chrooted users.

But since the mount kepts getting lost and I had grown tired of the users complaining that they couldn’t access the share. Plus it was taking too long manually remounting all the shares, let alone finding out which ones had become disconnected before the users started to complain. So I created a script to check and ask me if I wanted to mount the share.

Just so you know, this is my first time scripting in BASH and I only did it because of my short lived love with Linux. Below is an example of the code in my script, I basically created one of these functions for each user:

#TESTING USER3
if mountpoint -q /home/user3/ftp/files/share
 then
 echo "user3 is mounted"
 else
 echo "user3 is not mounted"
 read -p "Do you want to mount share? (y or n):" REPLY
 if [[ $REPLY = y ]]
  then
  mount --bind /home/shares/share/ /home/user3/ftp/files/share
 fi
fi

This way all I have to do is run this script and it will mount all of the shares for me. Let me know if there is an easier way to do this or if im missing something obviouse. Enjoy!