Jump to content

Change a text password to MD5 hash - save result to file


Recommended Posts

This is actually a two-part question..

1) I have a GUI where the user puts in a text-based password and I want it to convert/encrypt the text to MD5 Hash and copy the 20+ alpha/numeric result to a certain line of a text file. I have looked everywhere and cannot find any info on how this can be done. I can easily read the MD5 Hash but not write one based on a text password output.

2) This one might be tricky -- we want to restrict users when they change the text password so that it fits this criteria:

o Must be a minimum # # of characters (ie. 8+)

o One of those characters must be capitalized, and..

o One of those characters has to be a number.

Can Autoit do something like that?

My code:

#include <Crypt.au3>
#include <File.au3>

; Determine cfg paths
Local $TempDir=("\\<network_path>\")        ; network path to cfg 
Local $TempDir2=("C:\DATA\")                ; local path to cfg (used as backup)

; Choose alternate path if primary does not exist
If Not FileExists($TempDir) then
    Local $sav = $TempDir2 & '\ScreenSaver.cfg', $lticks, $GUI, $CGUI, $bl_ScreenSaver = False
    Local $sav = $TempDir2 & '\ScreenSaver.cfg', $lticks
    Local $w = @DesktopWidth, $h = @DesktopHeight, $sPath = FileReadLine($sav, 1)
Else
    Local $sav = $TempDir & '\ScreenSaver.cfg', $lticks, $GUI, $CGUI, $bl_ScreenSaver = False
    Local $sav = $TempDir & '\ScreenSaver.cfg', $lticks
    Local $w = @DesktopWidth, $h = @DesktopHeight, $sPath = FileReadLine($sav, 1)
endif
Opt('GUIOnEventMode', 1)

#Region Pref GUI
$PGUI = GUICreate('Screensaver Utility', 280, 150, -1, -1, BitOR(0x00040000, 0x00000080))
GUISetOnEvent(-3, '_PrefClose')

GUICtrlCreateGroup('Configuration Folder', 5, 5, 245, 42)
$p_pic = GUICtrlCreateEdit(FileReadLine($sav, 1), 10, 20, 170, 20, 2048 + 128)
GUICtrlCreateButton('Browse', 190, 20, 50, 20)
GUICtrlSetOnEvent(-1, '_Browse')

GUICtrlCreateGroup('Idle timeout', 170, 50, 80, 40)
$tidle = GUICtrlCreateEdit(FileReadLine($sav, 4), 180, 67, 60, 17, 8192 + 128)

GUICtrlCreateGroup('Enter new Password', 5, 50, 155, 40)
;~ $pass = GUICtrlCreateEdit(FileReadLine($sav, 5), 10, 65, 145, 20, 8192 + 128)    ; Displays existing MD5 Hash in the cfg file
$pass = GUICtrlCreateEdit("", 10, 65, 145, 20, 8192 + 128)

GUICtrlCreateButton('Apply', 80, 100, 80, 20)
GUICtrlSetOnEvent(-1, '_PrefApply')
GUISetState(@SW_HIDE, $PGUI)
#EndRegion Pref GUI

; Always run the application
_PrefOpen()

#Region Pref Func
Func _Browse()
    $path = FileSelectFolder('Select configuration folder', "", 1 + 2)
    If @error Then Exit ConsoleWrite('!> FileSelectFolder' & @CRLF)
    GUICtrlSetData($p_pic, $path & '\')
EndFunc   ;==>_Browse

Func _PrefApply()
    _FileWriteToLine($sav, 1, GUICtrlRead($p_pic), 1)   ; Write the new path location to the cfg
    If (GUICtrlRead($tidle) <> '') Then _FileWriteToLine($sav, 4, GUICtrlRead($tidle), 1)   ; Write the new timeout # to the cfg
    If (GUICtrlRead($tidle) = '') Then _FileWriteToLine($sav, 4, GUICtrlRead($tidle), 1)    ; Write the new timeout # to the cfg
;~  If (GUICtrlRead($pass) <> '') Then FileWrite($sav, 5)   ; Write the new password converted to MD5 Hash to the cfg (in progress)
;~  If (GUICtrlRead($pass) = '') Then FileWrite($sav, 5)    ; Write the new password converted to MD5 Hash to the cfg (in progress)

    Return Call('_PrefClose')
EndFunc   ;==>_PrefApply

Func _PrefOpen()
    GUICtrlSetData($p_pic, FileReadLine($sav, 1))
    GUICtrlSetData($tidle, FileReadLine($sav, 4))
;~  GUICtrlSetData($pass, FileReadLine($sav, 5))    ; Displays existing MD5 Hash in the cfg file
    GUISetState(@SW_SHOW, $PGUI)
EndFunc   ;==>_PrefOpen

Func _PrefClose()
    Exit GUISetState(@SW_HIDE, $PGUI)
EndFunc   ;==>_PrefClose
#EndRegion Pref Func

While 1
    Sleep(250)
WEnd
Thanks everyone! Edited by Thudo
Link to comment
Share on other sites

Why not just tell windows to require password complexity by local/group policy?

Admins and their scripts should NEVER need to know a user's password. Proper system config will handle it. There is no legitimate reason for an admin or script to need any access to the password string.

:blink:

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

Because we're not using Windows authentication via AD in our environment. Its done via local profiles. This all has to be done assuming its totally shut off and done via scripts. Yeah I know its quite unusual but we're only giving the app above to specific admins at various offices hence why only certain individuals will have access to change the password. Just the way we do things around here, brotha.

Link to comment
Share on other sites

Password complexity can be enforced on a stand alone machine via local security policy. A domain is not required.

It remains completely illegitimate for admins to handle user's password strings in any way.

:blink:

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

Set REG_DWORD HKCU\Software\Policies\Microsoft\Windows\Control Panel\Desktop\ScreenSaverIsSecure = 1.

What do you mean by "external screensaver"? How is it a screen saver if it's "external"?

I run the Folding@Home screen saver on lots of machines, and it has no problem letting Windows handle the authentication that way.

:blink:

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

Yeah I don't think you understand our environment. We lock EVERYTHING DOWN for certain machines: No right-click, no program files, no nothing except for Internet Explore. The SCR we are creating is an autoit script that checks idle time and has its own password facility. I still need help with Idle time out for the autoit screensaver but thats another story to submit another thread for.

Anyway how can "Set REG_DWORD HKCU\Software\Policies\Microsoft\Windows\Control Panel\Desktop\ScreenSaverIsSecure = 1" allow for us to set a password for our custom autoit password and then have certain people control its password and idle times? Remember we are building a screensaver that has its password and idle time out config'ed by a server that then controls these PCs in a certain area. Thats why we will send that app I mentioned in the first post to one PC per site per server to then control how the screensaver works in other PCs.

We're almost there -- we just need to fill in the final unknowns. Trust me: I'm used to a fully controlled Windows 7 AD environ but we're talking WinXP with SP1 and massively locked down. :blink: This is all being asked for a reason under exceptional circumstances.

Surely what I ask is doable of Autoit?

Link to comment
Share on other sites

  • Moderators

Thudo,

This script allows you to demand a certain level of complexity for a password - maybe it could be of use to you: :blink:

; original credit to mdiesel - aka Mat

$sRet = _PasswordCreate(7, 0, 2, 3, 1, 1)
If @error Then $sRet = "Cancelled"

MsgBox(0, "Password", $sRet)

Func _PasswordCreate($iMinLength, $fConfirm, $iDigits = 0, $iLowerCase = 0, $iUpperCase = 0, $iSpecialChars = 0)

    Local $Pass, $fConfirmPass, $Error

    If $iMinLength > 0 Then
        $fM = "M"
    Else
        $fM = ""
    EndIf

    Do
        $Pass = InputBox("Password", "Please enter your password", "", "*" & $fM)
        If @error Then Return SetError(1) ; Pass box cancelled

        If _CheckPasswordComplexity($Pass, $iMinLength, $iDigits, $iLowerCase, $iUpperCase, $iSpecialChars) = 0 Then
            $Error = "Password does not conform to the rules, it must have: "
            If $iMinLength > 0 Then $Error &= "a minimum length of " & $iMinLength & " Characters, "
            If $iDigits > 0 Then $Error &= "at least " & $iDigits & " Numbers, "
            If $iLowerCase > 0 Then $Error &= $iLowerCase & " or more lowercase characters, "
            If $iUpperCase > 0 Then $Error &= "no less than " & $iUpperCase & " Uppercase characters, "
            If $iSpecialChars > 0 Then $Error &= "at least " & $iSpecialChars & " Special characters such as punctuation, "
            $Error &= "Please change your password appropriately."
            MsgBox(48, "Error", $Error)
            ContinueLoop
        Else
            If $fConfirm Then
                $fConfirmPass = InputBox("Password", "Please Confirm your password", "", "*")
                If Not $fConfirmPass == $Pass Then MsgBox(48, "Error", "Passwords do not match")
            Else
                ExitLoop
            EndIf
        EndIf

    Until $Pass == $fConfirmPass

    Return $Pass

EndFunc   ;==>_PasswordCreate

Func _CheckPasswordComplexity($sPassword, $iMinLength, $iDigits = 0, $iLowerCase = 0, $iUpperCase = 0, $iSpecialChars = 0)

    Local $sRegExp = "^.*(?=.{" & $iMinLength & ",})"
    If $iDigits > 0 Then $sRegExp &= "(?=.*[[:digit:]]{" & $iDigits & ",})"
    If $iLowerCase > 0 Then $sRegExp &= "(?=.*[[:lower:]]{" & $iLowerCase & ",})"
    If $iUpperCase > 0 Then $sRegExp &= "(?=.*[[:upper:]]{" & $iUpperCase & ",})"
    If $iSpecialChars > 0 Then $sRegExp &= "(?=.*[[:punct:]]{" & $iSpecialChars & ",})"

    $sRegExp &= ".*$"

    Local $iResult = StringRegExp($sPassword, $sRegExp)
    If @error = 0 Then
        Return SetError(0, 0, ($iResult <> 0))
    Else
        Return SetError(1, 0, 0)
    EndIf

EndFunc   ;==>_CheckPasswordComplexity

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Thank you very much Melba/Mat. Thats precisely where I need to go..

However, how do I integrate all that into the original code from the first post?

It has to somehow detect the user input from:

GUICtrlCreateGroup('Enter new Password', 5, 50, 155, 40)
$pass = GUICtrlCreateEdit("", 10, 65, 145, 20, 8192 + 128)
Edited by Thudo
Link to comment
Share on other sites

  • Moderators

Thudo,

how do I integrate all that into the original code from the first post?

What code have you tried that did not work? :blink:

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

hehe.. well I know the code you posted above works amazing but its the integration into my first post that I am trying to figure out. However, yeah.. that code is 100% precisely what we want except how to replace your Input box with the GUI we already have.

Link to comment
Share on other sites

  • Moderators

Thudo,

the integration into my first post that I am trying to figure out

Systems integration is always the tough bit! ;)

But unless you show a bit more initiative than gently prodding in the hope that someone will give you a ready-made solution, you are not going to get a lot more help. Post some code where you have tried and failed to integrate the 2 scripts and you could well have a lot more luck. :blink:

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

I'll get the integration done.. I mean got this far :blink:

What about #1 - the MD5 encryption? Essentially it has to take the result from #2 then convert it to the hash and dump into a file. That part stumps me as I haven't found a reliable way to dump user data to MD5 reliably. :|

Link to comment
Share on other sites

  • Moderators

Thudo,

Give it a shot - you know where we are if you run into problems. ;)

As to the MD5 hash - I use _Crypt_HashData($sData, $CALG_MD5) for a script I use every day and it has never let me down yet. :blink:

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

I'll get the integration done.. I mean got this far :blink:

What about #1 - the MD5 encryption? Essentially it has to take the result from #2 then convert it to the hash and dump into a file. That part stumps me as I haven't found a reliable way to dump user data to MD5 reliably. :|

MD5 Example from the help file:

#include  <Crypt.au3>

; Example of hashing data and using it to authenticate password

; This is the MD5-hash of the correct password
$bPasswordHash="0xCE950A8D7D367B5CE038E636893B49DC"

$sPassword=InputBox("Login","Please type the correct password.","Yellow fruit that is popular among monkeys")

If _Crypt_HashData($sPassword,$CALG_MD5)=$bPasswordHash Then
    MsgBox(64,"Access Granted","Password correct!")
Else
    MsgBox(16,"Access Denied","You entered the wrong password!")
EndIf
Spoiler

Things I've Made: Always On Top Tool ◊ AU History ◊ Deck of Cards ◊ HideIt ◊ ICU ◊ Icon Freezer ◊ Ipod Ejector ◊ Junos Configuration Explorer ◊ Link Downloader ◊ MD5 Folder Enumerator ◊ PassGen ◊ Ping Tool ◊ Quick NIC ◊ Read OCR ◊ RemoteIT ◊ SchTasksGui ◊ SpyCam ◊ System Scan Report Tool ◊ System UpTime ◊ Transparency Machine ◊ VMWare ESX Builder
Misc Code Snippets: ADODB Example ◊ CheckHover ◊ Detect SafeMode ◊ DynEnumArray ◊ GetNetStatData ◊ HashArray ◊ IsBetweenDates ◊ Local Admins ◊ Make Choice ◊ Recursive File List ◊ Remove Sizebox Style ◊ Retrieve PNPDeviceID ◊ Retreive SysListView32 Contents ◊ Set IE Homepage ◊ Tickle Expired Password ◊ Transpose Array
Projects: Drive Space Usage GUI ◊ LEDkIT ◊ Plasma_kIt ◊ Scan Engine Builder ◊ SpeeDBurner ◊ SubnetCalc
Cool Stuff: AutoItObject UDF â—Š Extract Icon From Proc â—Š GuiCtrlFontRotate â—Š Hex Edit Funcs â—Š Run binary â—Š Service_UDF

 

Link to comment
Share on other sites

Hmm.. I've used _Crypt_HashData($sData, $CALG_MD5)but never used it to actually create a hash from text -- only for detection as per spud's helpfile dump. That works.. its the other way where you create the hash from a user's input I haven't had any luck.

Link to comment
Share on other sites

Hmm.. I've used _Crypt_HashData($sData, $CALG_MD5)but never used it to actually create a hash from text -- only for detection as per spud's helpfile dump. That works.. its the other way where you create the hash from a user's input I haven't had any luck.

You simply feed the _Crypt_HashData() function the text you want to hash, and it returns the encrypted Hash.

How you supply the text to the function is up to you. The example prompts for input via an InputBox.

edit: typo

Edited by spudw2k
Spoiler

Things I've Made: Always On Top Tool ◊ AU History ◊ Deck of Cards ◊ HideIt ◊ ICU ◊ Icon Freezer ◊ Ipod Ejector ◊ Junos Configuration Explorer ◊ Link Downloader ◊ MD5 Folder Enumerator ◊ PassGen ◊ Ping Tool ◊ Quick NIC ◊ Read OCR ◊ RemoteIT ◊ SchTasksGui ◊ SpyCam ◊ System Scan Report Tool ◊ System UpTime ◊ Transparency Machine ◊ VMWare ESX Builder
Misc Code Snippets: ADODB Example ◊ CheckHover ◊ Detect SafeMode ◊ DynEnumArray ◊ GetNetStatData ◊ HashArray ◊ IsBetweenDates ◊ Local Admins ◊ Make Choice ◊ Recursive File List ◊ Remove Sizebox Style ◊ Retrieve PNPDeviceID ◊ Retreive SysListView32 Contents ◊ Set IE Homepage ◊ Tickle Expired Password ◊ Transpose Array
Projects: Drive Space Usage GUI ◊ LEDkIT ◊ Plasma_kIt ◊ Scan Engine Builder ◊ SpeeDBurner ◊ SubnetCalc
Cool Stuff: AutoItObject UDF â—Š Extract Icon From Proc â—Š GuiCtrlFontRotate â—Š Hex Edit Funcs â—Š Run binary â—Š Service_UDF

 

Link to comment
Share on other sites

You simply feed the _Crypt_HashData() function the text you want to hash, and it returns the encrypted Hash.

How you supply the text to the function is up to you. The example prompts for input via an InputBox.

I'll give that also a try and report in. :blink:
Link to comment
Share on other sites

Hmm ok I can say I'm honest stuck playing with this great script..

Have great angst getting that GUI to use what would normally be done with the Input Box.

The code:

$sRet = _PasswordCreate(7, 0, 2, 3, 1)
If @error Then $sRet = "Cancelled"

;~ MsgBox(0, "Password", $sRet)

    #Region Pref GUI
    $PGUI = GUICreate('Screensaver Utility', 280, 150, -1, -1, BitOR(0x00040000, 0x00000080))
    GUICtrlCreateGroup('Enter new Password', 5, 50, 155, 40)
    $pass = GUICtrlCreateEdit("", 10, 65, 145, 20, 8192 + 128)
    #EndRegion Pref GUI
    GUISetState(@SW_SHOW, $PGUI)
    
Func _PasswordCreate($iMinLength, $fConfirm, $iDigits = 0, $iLowerCase = 0, $iUpperCase = 0)

    Local $Pass, $fConfirmPass, $Error

    If $iMinLength > 0 Then
        $fM = "M"
    Else
        $fM = ""
    EndIf

    Do
;~         $Pass = InputBox("Password", "Please enter your password", "", "*" & $fM)
           $Pass = GUICtrlCreateEdit("", 10, 65, 145, 20, 8192 + 128)

        If @error Then Return SetError(1) ; Pass box cancelled

        If _CheckPasswordComplexity($Pass, $iMinLength, $iDigits, $iLowerCase, $iUpperCase) = 0 Then
            $Error = "Password does not conform to the rules, it must have: "
            If $iMinLength > 0 Then $Error &= "a minimum length of " & $iMinLength & " Characters, "
            If $iDigits > 0 Then $Error &= "at least " & $iDigits & " Numbers, "
            If $iLowerCase > 0 Then $Error &= $iLowerCase & " or more lowercase characters, "
            If $iUpperCase > 0 Then $Error &= "no less than " & $iUpperCase & " Uppercase characters, "
            $Error &= "Please change your password appropriately."
            MsgBox(48, "Error", $Error)
            ContinueLoop
        Else
            If $fConfirm Then
                $fConfirmPass = InputBox("Password", "Please Confirm your password", "", "*")
                If Not $fConfirmPass == $Pass Then MsgBox(48, "Error", "Passwords do not match")
            Else
                ExitLoop
            EndIf
        EndIf

    Until $Pass == $fConfirmPass

    Return $Pass

EndFunc   ;==>_PasswordCreate

Func _CheckPasswordComplexity($sPassword, $iMinLength, $iDigits = 0, $iLowerCase = 0, $iUpperCase = 0)

    Local $sRegExp = "^.*(?=.{" & $iMinLength & ",})"
    If $iDigits > 0 Then $sRegExp &= "(?=.*[[:digit:]]{" & $iDigits & ",})"
    If $iLowerCase > 0 Then $sRegExp &= "(?=.*[[:lower:]]{" & $iLowerCase & ",})"
    If $iUpperCase > 0 Then $sRegExp &= "(?=.*[[:upper:]]{" & $iUpperCase & ",})"

    $sRegExp &= ".*$"

    Local $iResult = StringRegExp($sPassword, $sRegExp)
    If @error = 0 Then
        Return SetError(0, 0, ($iResult <> 0))
    Else
        Return SetError(1, 0, 0)
    EndIf

EndFunc   ;==>_CheckPasswordComplexity
On its own the GUI is fine but having considerable pains integrating it with that code. Once I do, I can then work on the HashData function. Thanks for your patience, team!
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...