diff --git a/account.php b/account.php
new file mode 100644
index 0000000000000000000000000000000000000000..3391e46bcb2da1fd1cb8c1db83b33ac3f28475f2
--- /dev/null
+++ b/account.php
@@ -0,0 +1,60 @@
+<?php
+/*********************************************************************
+    profile.php
+
+    Manage client profile. This will allow a logged-in user to manage
+    his/her own public (non-internal) information
+
+    Peter Rotich <peter@osticket.com>
+    Jared Hancock <jared@osticket.com>
+    Copyright (c)  2006-2013 osTicket
+    http://www.osticket.com
+
+    Released under the GNU General Public License WITHOUT ANY WARRANTY.
+    See LICENSE.TXT for details.
+
+    vim: expandtab sw=4 ts=4 sts=4:
+    $Id: $
+**********************************************************************/
+require 'client.inc.php';
+
+$inc = 'register.inc.php';
+
+if (!$cfg || !$cfg->isClientRegistrationEnabled()) {
+    Http::redirect('index.php');
+}
+
+elseif ($_POST) {
+    $errors = array();
+    $user_form = UserForm::getUserForm()->getForm($_POST);
+    if (!$user_form->isValid(function($f) { return !$f->get('internal'); }))
+        $errors['err'] = 'Incomplete client information';
+    elseif (!$_POST['passwd1'])
+        $errors['passwd1'] = 'New password required';
+    elseif ($_POST['passwd2'] != $_POST['passwd1'])
+        $errors['passwd1'] = 'Passwords do not match';
+
+    elseif (!($user=User::fromForm($user_form)))
+        $errors['err'] = 'Unable to register account. See messages below';
+    else {
+        if (!($acct = ClientAccount::createForUser($user)))
+            $errors['err'] = 'Internal error. Unable to create new account';
+        elseif (!$acct->update($_POST, $errors))
+            $errors['err'] = 'Errors configuring your profile. See messages below';
+    }
+
+    if (!$errors) {
+        switch ($_POST['do']) {
+        case 'create':
+            $inc = 'register.confirm.inc.php';
+        }
+    }
+
+    if ($errors && $user)
+        $user->delete();
+}
+
+include(CLIENTINC_DIR.'header.inc.php');
+include(CLIENTINC_DIR.$inc);
+include(CLIENTINC_DIR.'footer.inc.php');
+
diff --git a/include/class.client.php b/include/class.client.php
index 8e5deee12c024e840ebbe87764ece8d4be477770..c5ea785cd15cd144493ea5129de84b57a906627f 100644
--- a/include/class.client.php
+++ b/include/class.client.php
@@ -420,12 +420,14 @@ class ClientAccount extends ClientAccountModel {
                     $errors['err'] =
                         'Invalid reset token. Logout and try again';
             }
-            elseif (!$vars['cpasswd'])
-                $errors['cpasswd']='Current password required';
-            elseif (!$this->hasCurrentPassword($vars['cpasswd']))
-                $errors['cpasswd']='Invalid current password!';
-            elseif (!strcasecmp($vars['passwd1'], $vars['cpasswd']))
-                $errors['passwd1']='New password MUST be different from the current password!';
+            elseif ($this->get('passwd')) {
+                if (!$vars['cpasswd'])
+                    $errors['cpasswd']='Current password required';
+                elseif (!$this->hasCurrentPassword($vars['cpasswd']))
+                    $errors['cpasswd']='Invalid current password!';
+                elseif (!strcasecmp($vars['passwd1'], $vars['cpasswd']))
+                    $errors['passwd1']='New password MUST be different from the current password!';
+            }
         }
 
         if (!$vars['timezone_id'])
@@ -447,6 +449,10 @@ class ClientAccount extends ClientAccountModel {
         return $this->save();
     }
 
+    static function createForUser($user) {
+        return static::create(array('user_id'=>$user->getId()));
+    }
+
     static function lookupByUsername($username) {
         if (strpos($username, '@') !== false)
             $user = self::lookup(array('user__emails__address'=>$username));
diff --git a/include/class.config.php b/include/class.config.php
index 34aabc4180ed18846acaabc93b7403bb038ecfcf..7d1a9013656597bd7a3d4575c4f8253737b8c531 100644
--- a/include/class.config.php
+++ b/include/class.config.php
@@ -241,6 +241,10 @@ class OsticketConfig extends Config {
         return $this->get('db_tz_offset');
     }
 
+    function getDefaultTimezoneId() {
+        return $this->get('default_timezone_id');
+    }
+
     /* Date & Time Formats */
     function observeDaylightSaving() {
         return ($this->get('enable_daylight_saving'));
@@ -523,6 +527,15 @@ class OsticketConfig extends Config {
         return $this->get('clients_only');
     }
 
+    function isClientRegistrationEnabled() {
+        return in_array($this->getClientRegistrationMode(),
+            array('public', 'auto'));
+    }
+
+    function getClientRegistrationMode() {
+        return $this->get('client_registration');
+    }
+
     function isCaptchaEnabled() {
         return (extension_loaded('gd') && function_exists('gd_info') && $this->get('enable_captcha'));
     }
diff --git a/include/class.user.php b/include/class.user.php
index c465f095fc3acbf684f888d4578159e80f95272b..d23d1e9f1b857bd343f74c42bc7348580703df56 100644
--- a/include/class.user.php
+++ b/include/class.user.php
@@ -292,6 +292,10 @@ class User extends UserModel {
             $this->set('updated', new SqlFunction('NOW'));
         return parent::save($refetch);
     }
+
+    function delete() {
+        return parent::delete() && $this->default_email->delete();
+    }
 }
 User::_inspect();
 
diff --git a/include/client/login.inc.php b/include/client/login.inc.php
index 9dc62eb571dc0ed81e380f87d516a4f47a995d2c..2a505ef84771440cf6cb4399d11ef4fa3bee9263 100644
--- a/include/client/login.inc.php
+++ b/include/client/login.inc.php
@@ -7,7 +7,8 @@ $passwd=Format::input($_POST['lpasswd']?:$_GET['t']);
 <h1>Sign In</h1>
 <form action="login.php" method="post" id="clientLogin">
     <?php csrf_token(); ?>
-    <div style="width:50%;display:inline-block">
+<div style="display:table-row">
+    <div style="width:40%;display:table-cell">
     <strong><?php echo Format::htmlchars($errors['login']); ?></strong>
     <br>
     <div>
@@ -21,9 +22,17 @@ $passwd=Format::input($_POST['lpasswd']?:$_GET['t']);
     <p>
         <input class="btn" type="submit" value="Sign In">
     </p>
+    </div>
+<?php if ($cfg && $cfg->isClientRegistrationEnabled()) { ?>
+    <div style="display:table-cell;box-shadow: -9px 0 15px -12px rgba(0,0,0,0.3);padding-left: 2em;">
+        Not yet registered? <a href="account.php?do=create">Create an account</a>
+    </div>
+<?php } ?>
 </div>
 </form>
 <br>
 <p>
+<?php if ($cfg && !$cfg->isClientLoginRequired()) { ?>
 If this is your first time contacting us or you've lost the ticket number, please <a href="open.php">open a new ticket</a>.
+<?php } ?>
 </p>
diff --git a/include/client/register.confirm.inc.php b/include/client/register.confirm.inc.php
new file mode 100644
index 0000000000000000000000000000000000000000..7e8ed820e653b1602bfc49ebe9a263934f523490
--- /dev/null
+++ b/include/client/register.confirm.inc.php
@@ -0,0 +1,9 @@
+<h1>Account Registration</h1>
+<p>
+<strong>Thanks for registering for an account.</strong>
+</p>
+<p>
+We've just sent you an email to the address you entered. Please follow the
+link in the email to confirm your account and gain access to your tickets.
+</p>
+
diff --git a/include/client/register.inc.php b/include/client/register.inc.php
new file mode 100644
index 0000000000000000000000000000000000000000..71e54eb8027f7aba7420d0e5792d3cd88b55c86f
--- /dev/null
+++ b/include/client/register.inc.php
@@ -0,0 +1,83 @@
+<?php
+$info = $_POST ?: array(
+    'timezone_id' => $cfg->getDefaultTimezoneId(),
+    'dst' => $cfg->observeDaylightSaving(),
+);
+?>
+<h1>Account Registration</h1>
+<p>
+Use the forms below to update the information we have on file for your
+account
+</p>
+<form action="account.php" method="post">
+  <?php csrf_token(); ?>
+  <input type="hidden" name="do" value="<?php echo $_REQUEST['do'] ?: 'create'; ?>" />
+<table width="800" class="padded">
+<?php
+    $cf = $user_form ?: UserForm::getInstance();
+    $cf->render(false);
+?>
+<tr>
+    <td colspan="2">
+        <div><hr><h3>Preferences</h3>
+        </div>
+    </td>
+</tr>
+    <td>Time Zone:</td>
+    <td>
+        <select name="timezone_id" id="timezone_id">
+            <?php
+            $sql='SELECT id, offset,timezone FROM '.TIMEZONE_TABLE.' ORDER BY id';
+            if(($res=db_query($sql)) && db_num_rows($res)){
+                while(list($id,$offset, $tz)=db_fetch_row($res)){
+                    $sel=($info['timezone_id']==$id)?'selected="selected"':'';
+                    echo sprintf('<option value="%d" %s>GMT %s - %s</option>',$id,$sel,$offset,$tz);
+                }
+            }
+            ?>
+        </select>
+        &nbsp;<span class="error"><?php echo $errors['timezone_id']; ?></span>
+    </td>
+</tr>
+<tr>
+    <td width="180">
+       Daylight Saving:
+    </td>
+    <td>
+        <input type="checkbox" name="dst" value="1" <?php echo $info['dst']?'checked="checked"':''; ?>>
+        Observe daylight saving
+        <em>(Current Time: <strong><?php echo Format::date($cfg->getDateTimeFormat(),Misc::gmtime(),$info['tz_offset'],$info['dst']); ?></strong>)</em>
+    </td>
+</tr>
+<tr>
+    <td colspan=2">
+        <div><hr><h3>Access Credentials</h3></div>
+    </td>
+</tr>
+<tr>
+    <td width="180">
+        Create a Password:
+    </td>
+    <td>
+        <input type="password" size="18" name="passwd1" value="<?php echo $info['passwd1']; ?>">
+        &nbsp;<span class="error">&nbsp;<?php echo $errors['passwd1']; ?></span>
+    </td>
+</tr>
+<tr>
+    <td width="180">
+        Confirm New Password:
+    </td>
+    <td>
+        <input type="password" size="18" name="passwd2" value="<?php echo $info['passwd2']; ?>">
+        &nbsp;<span class="error">&nbsp;<?php echo $errors['passwd2']; ?></span>
+    </td>
+</tr>
+</table>
+<hr>
+<p style="text-align: center;">
+    <input type="submit" value="Register"/>
+    <input type="button" value="Cancel" onclick="javascript:
+        window.location.href='index.php';"/>
+</p>
+</form>
+