yms/yms.php
changeset 0 9997bee9ad03
child 1 765356a05643
equal deleted inserted replaced
-1:000000000000 0:9997bee9ad03
       
     1 <?php
       
     2 
       
     3 function page_Special_YMS()
       
     4 {
       
     5   global $db, $session, $paths, $template, $plugins; // Common objects
       
     6   global $lang;
       
     7   global $output;
       
     8   
       
     9   // Require re-auth?
       
    10   if ( $session->auth_level < USER_LEVEL_CHPREF && getConfig('yms_require_reauth', 1) == 1 )
       
    11   {
       
    12     redirect(makeUrlNS('Special', "Login/$paths->fullpage", 'level=' . USER_LEVEL_CHPREF), '', '', 0);
       
    13   }
       
    14   
       
    15   // Check for Yubikey plugin
       
    16   if ( !function_exists('yubikey_validate_otp') )
       
    17   {
       
    18     die_friendly($lang->get('yms_err_yubikey_plugin_missing_title'), '<p>' . $lang->get('yms_err_yubikey_plugin_missing_body') . '</p>');
       
    19   }
       
    20   
       
    21   // Does the client exist?
       
    22   $q = $db->sql_query('SELECT 1 FROM ' . table_prefix . "yms_clients WHERE id = {$session->user_id};");
       
    23   if ( !$q )
       
    24     $db->_die();
       
    25   
       
    26   $client_exists = $db->numrows();
       
    27   $db->free_result();
       
    28   if ( !$client_exists )
       
    29   {
       
    30     redirect(makeUrlNS('Special', 'YMSCreateClient'), '', '', 0);
       
    31   }
       
    32   
       
    33   // Check for a subpage request
       
    34   if ( $subpage = $paths->getParam(0) )
       
    35   {
       
    36     if ( preg_match('/^[A-z0-9]+$/', $subpage) )
       
    37     {
       
    38       if ( function_exists("page_Special_YMS_{$subpage}") )
       
    39       {
       
    40         // call the subpage
       
    41         return call_user_func("page_Special_YMS_{$subpage}");
       
    42       }
       
    43     }
       
    44   }
       
    45   
       
    46   //
       
    47   // POST processing
       
    48   //
       
    49   
       
    50   if ( isset($_POST['add_aes']) && isset($_POST['add_otp']) )
       
    51   {
       
    52     $client_id = false;
       
    53     $enabled = $_POST['state'] == 'active';
       
    54     $any_client = isset($_POST['any_client']);
       
    55     $notes = $_POST['notes'];
       
    56     $result = yms_add_yubikey($_POST['add_aes'], $_POST['add_otp'], $client_id, $enabled, $any_client, $notes);
       
    57     yms_send_response('yms_msg_addkey_success', $result);
       
    58   }
       
    59   else if ( isset($_POST['claim_otp']) )
       
    60   {
       
    61     // do we need to validate a custom field?
       
    62     if ( ($url = getConfig('yms_claim_auth_url')) && getConfig('yms_claim_auth_field') )
       
    63     {
       
    64       if ( ($result = yms_validate_custom_field($_POST['custom_field'], $_POST['claim_otp'], $url)) !== true )
       
    65         yms_send_response('n/a', $result);
       
    66     }
       
    67     
       
    68     // validate this OTP, make sure it's all good
       
    69     $result = strtolower(yms_validate_otp($_POST['claim_otp'], 0));
       
    70     if ( $result !== 'ok' )
       
    71       yms_send_response('n/a', "yubiauth_err_response_{$result}");
       
    72     
       
    73     // change owner
       
    74     $client_id = false;
       
    75     $enabled = $_POST['state'] == 'active';
       
    76     $any_client = isset($_POST['any_client']);
       
    77     $notes = $_POST['notes'];
       
    78     $result = yms_chown_yubikey($_POST['claim_otp'], $client_id, $enabled, $any_client, $notes);
       
    79     yms_send_response('yms_msg_addkey_success', $result);
       
    80   }
       
    81   
       
    82   // Preload JS libraries we need for Yubikey
       
    83   $template->preload_js(array('jquery', 'jquery-ui', 'l10n', 'flyin', 'messagebox', 'fadefilter'));
       
    84   // Load CSS
       
    85   $template->add_header('<link rel="stylesheet" type="text/css" href="' . scriptPath . '/plugins/yms/styles.css" />');
       
    86   // Load JS
       
    87   $template->add_header('<script type="text/javascript" src="' . scriptPath . '/plugins/yms/cp.js"></script>');
       
    88   
       
    89   // Send header
       
    90   $output->header();
       
    91   
       
    92   // Message container
       
    93   if ( !isset($_GET['ajax'] ) )
       
    94     echo '<div id="yms-messages"></div><div id="yms-keylist">';
       
    95   
       
    96   // Buttons
       
    97   ?>
       
    98   <div class="yms-buttons">
       
    99     <a class="abutton abutton_green icon" style="background-image: url(<?php echo scriptPath; ?>/plugins/yms/icons/key_add.png);"
       
   100        href="<?php echo makeUrlNS('Special', 'YMS/AddKey'); ?>" onclick="yms_showpage('AddKey'); return false;">
       
   101       <?php echo $lang->get('yms_btn_add_key'); ?>
       
   102     </a>
       
   103     <a class="abutton abutton_blue icon" style="background-image: url(<?php echo scriptPath; ?>/plugins/yms/icons/key_add.png);"
       
   104        href="<?php echo makeUrlNS('Special', 'YMS/AddPreregisteredKey'); ?>" onclick="yms_showpage('AddPreregisteredKey'); return false;">
       
   105       <?php echo $lang->get('yms_btn_add_key_preregistered'); ?>
       
   106     </a>
       
   107   </div>
       
   108   <?php
       
   109   
       
   110   // Pull all Yubikeys
       
   111   $q = $db->sql_query('SELECT id, public_id, session_count, create_time, access_time, flags, notes FROM ' . table_prefix . "yms_yubikeys WHERE client_id = {$session->user_id};");
       
   112   if ( !$q )
       
   113     $db->_die();
       
   114   
       
   115   if ( $db->numrows() < 1 )
       
   116   {
       
   117     echo '<h2 class="emptymessage">' . $lang->get('yms_msg_no_yubikeys') . '</h2>';
       
   118   }
       
   119   else
       
   120   {
       
   121     ?>
       
   122     <div class="tblholder">
       
   123     <table border="0" cellspacing="1" cellpadding="4">
       
   124     
       
   125     <!-- Table header -->
       
   126       <tr>
       
   127         <th><?php echo $lang->get('yms_th_id'); ?></th>
       
   128         <th><?php echo $lang->get('yms_th_publicid'); ?></th>
       
   129         <th><?php echo $lang->get('yms_th_createtime'); ?></th>
       
   130         <th><?php echo $lang->get('yms_th_accesstime'); ?></th>
       
   131         <th><?php echo $lang->get('yms_th_state'); ?></th>
       
   132         <th><?php echo $lang->get('yms_th_note'); ?></th>
       
   133         <th></th>
       
   134       </tr>
       
   135     
       
   136     <?php
       
   137       $cls = 'row2';
       
   138       while ( $row = $db->fetchrow($q) )
       
   139       {
       
   140         $cls = $cls == 'row2' ? 'row1' : 'row2';
       
   141         ?>
       
   142         <tr>
       
   143           <!-- Key ID -->
       
   144           <td style="text-align: center;" class="<?php echo $cls; ?>"><?php echo $row['id']; ?></td>
       
   145           
       
   146           <!-- Public UID -->
       
   147           <td style="text-align: left;" class="<?php echo $cls; ?>"><?php echo yms_modhex_encode($row['public_id']); ?></td>
       
   148           
       
   149           <!-- Create time -->
       
   150           <td style="text-align: left;" class="<?php echo $cls; ?>"><?php echo yms_date($row['create_time']); ?></td>
       
   151           
       
   152           <!-- Access time -->
       
   153           <td style="text-align: left;" class="<?php echo $cls; ?>"><?php echo $row['access_time'] <= $row['create_time'] ? $lang->get('yms_msg_access_never') : yms_date($row['access_time']); ?></td>
       
   154           
       
   155           <!-- State -->
       
   156           <td style="text-align: center;" class="<?php echo $cls; ?>"><?php echo yms_state_indicator($row['flags'], $row['id']); ?></td>
       
   157           
       
   158           <!-- Notes -->
       
   159           <td style="text-align: center;" class="<?php echo $cls; ?>"><?php echo yms_notes_cell($row['notes'], $row['id']); ?></td>
       
   160           
       
   161           <!-- Actions -->
       
   162           <td style="text-align: center;" class="<?php echo $cls; ?>"><?php echo yms_show_actions($row);  ?></td>
       
   163         </tr>
       
   164         <?php
       
   165       }
       
   166     ?>
       
   167     
       
   168     </table>
       
   169     </div>
       
   170     
       
   171     <br /><br />
       
   172     <a href="<?php echo makeUrlNS('Special', 'YMS/Converter'); ?>" onclick="yms_showpage('Converter'); return false;" class="abutton abutton_red icon"
       
   173        style="background-image: url(<?php echo scriptPath; ?>/plugins/yms/icons/application_view_icons.png);">
       
   174       <?php echo $lang->get('yms_btn_show_converter'); ?>
       
   175     </a>
       
   176     
       
   177     <a href="<?php echo makeUrlNS('Special', 'YMS/Converter'); ?>" onclick="yms_showpage('ShowClientInfo'); return false;" class="abutton abutton_blue icon"
       
   178        style="background-image: url(<?php echo scriptPath; ?>/plugins/yms/icons/show_client_info.png);">
       
   179       <?php echo $lang->get('yms_btn_show_client_info'); ?>
       
   180     </a>
       
   181     
       
   182     <?php
       
   183   }
       
   184   $db->free_result($q);
       
   185   
       
   186   // close off inner div (yms-keylist)
       
   187   if ( !isset($_GET['ajax'] ) )
       
   188     echo '</div>';
       
   189   
       
   190   // Send footer
       
   191   $output->footer();
       
   192 }
       
   193 
       
   194 // Add key, using AES secret
       
   195 function page_Special_YMS_AddKey()
       
   196 {
       
   197   global $output;
       
   198   global $lang;
       
   199   
       
   200   $output->header();
       
   201   ?>
       
   202   <h3><?php echo $lang->get('yms_lbl_addkey_heading'); ?></h3>
       
   203   <p><?php echo $lang->get('yms_lbl_addkey_desc'); ?></p>
       
   204   <form action="<?php echo makeUrlNS('Special', 'YMS'); ?>" method="post">
       
   205   
       
   206     <div class="tblholder">
       
   207     <table border="0" cellspacing="1" cellspacing="4">
       
   208     
       
   209       <!-- AES secret -->
       
   210       <tr>
       
   211         <td class="row2">
       
   212           <?php echo $lang->get('yms_lbl_addkey_field_secret'); ?><br />
       
   213           <small><?php echo $lang->get('yms_lbl_addkey_field_secret_hint'); ?></small>
       
   214         </td>
       
   215         <td class="row1">
       
   216           <input type="text" name="add_aes" value="" size="40" />
       
   217         </td>
       
   218       </tr>
       
   219       
       
   220       <!-- OTP -->
       
   221       <tr>
       
   222         <td class="row2">
       
   223           <?php echo $lang->get('yms_lbl_addkey_field_otp'); ?>
       
   224         </td>
       
   225         <td class="row1">
       
   226           <?php echo generate_yubikey_field('add_otp'); ?>
       
   227         </td>
       
   228       </tr>
       
   229       
       
   230       <!-- State -->
       
   231       <tr>
       
   232         <td class="row2">
       
   233           <?php echo $lang->get('yms_lbl_addkey_field_state'); ?>
       
   234         </td>
       
   235         <td class="row1">
       
   236           <select name="state">
       
   237             <option value="active" selected="selected"><?php echo $lang->get('yms_state_active'); ?></option>
       
   238             <option value="inactive"><?php echo $lang->get('yms_state_inactive'); ?></option>
       
   239           </select>
       
   240         </td>
       
   241       </tr>
       
   242       
       
   243       <!-- Any client -->
       
   244       <tr>
       
   245         <td class="row2">
       
   246           <?php echo $lang->get('yms_lbl_addkey_field_any_client_name'); ?><br />
       
   247           <small><?php echo $lang->get('yms_lbl_addkey_field_any_client_hint'); ?></small>
       
   248         </td>
       
   249         <td class="row1">
       
   250           <label>
       
   251             <input type="checkbox" name="any_client" />
       
   252             <?php echo $lang->get('yms_lbl_addkey_field_any_client'); ?>
       
   253           </label>
       
   254         </td>
       
   255       </tr>
       
   256       
       
   257       <!-- Notes -->
       
   258       <tr>
       
   259         <td class="row2">
       
   260           <?php echo $lang->get('yms_lbl_addkey_field_notes'); ?>
       
   261         </td>
       
   262         <td class="row1">
       
   263           <textarea style="font-family: sans-serif; font-size: 9pt;" name="notes" rows="5" cols="40"></textarea>
       
   264         </td>
       
   265       </tr>
       
   266       
       
   267       <!-- Submit -->
       
   268       <tr>
       
   269         <th class="subhead" colspan="2">
       
   270           <input type="submit" value="<?php echo $lang->get('yms_btn_addkey_submit'); ?>" />
       
   271         </th>
       
   272       </tr>
       
   273       
       
   274     </table>
       
   275     </div>
       
   276   
       
   277   </form>
       
   278   <?php
       
   279   $output->footer();
       
   280 }
       
   281 
       
   282 // Add key that's already registered
       
   283 function page_Special_YMS_AddPreregisteredKey()
       
   284 {
       
   285   global $db, $session, $paths, $template, $plugins; // Common objects
       
   286   global $lang, $output;
       
   287   
       
   288   $output->header();
       
   289   ?>
       
   290   <h3><?php echo $lang->get('yms_lbl_claimkey_heading'); ?></h3>
       
   291   <p><?php echo $lang->get('yms_lbl_claimkey_desc'); ?></p>
       
   292   <form action="<?php echo makeUrlNS('Special', 'YMS'); ?>" method="post">
       
   293   
       
   294     <div class="tblholder">
       
   295     <table border="0" cellspacing="1" cellspacing="4">
       
   296     
       
   297       <!-- OTP -->
       
   298       <tr>
       
   299         <td class="row2">
       
   300           <?php echo $lang->get('yms_lbl_addkey_field_otp'); ?>
       
   301         </td>
       
   302         <td class="row1">
       
   303           <?php echo generate_yubikey_field('claim_otp'); ?>
       
   304         </td>
       
   305       </tr>
       
   306       
       
   307       <!-- State -->
       
   308       <tr>
       
   309         <td class="row2">
       
   310           <?php echo $lang->get('yms_lbl_addkey_field_state'); ?>
       
   311         </td>
       
   312         <td class="row1">
       
   313           <select name="state">
       
   314             <option value="active" selected="selected"><?php echo $lang->get('yms_state_active'); ?></option>
       
   315             <option value="inactive"><?php echo $lang->get('yms_state_inactive'); ?></option>
       
   316           </select>
       
   317         </td>
       
   318       </tr>
       
   319       
       
   320       <!-- Any client -->
       
   321       <tr>
       
   322         <td class="row2">
       
   323           <?php echo $lang->get('yms_lbl_addkey_field_any_client_name'); ?><br />
       
   324           <small><?php echo $lang->get('yms_lbl_addkey_field_any_client_hint'); ?></small>
       
   325         </td>
       
   326         <td class="row1">
       
   327           <label>
       
   328             <input type="checkbox" name="any_client" />
       
   329             <?php echo $lang->get('yms_lbl_addkey_field_any_client'); ?>
       
   330           </label>
       
   331         </td>
       
   332       </tr>
       
   333       
       
   334       <!-- Notes -->
       
   335       <tr>
       
   336         <td class="row2">
       
   337           <?php echo $lang->get('yms_lbl_addkey_field_notes'); ?>
       
   338         </td>
       
   339         <td class="row1">
       
   340           <textarea style="font-family: sans-serif; font-size: 9pt;" name="notes" rows="5" cols="40"></textarea>
       
   341         </td>
       
   342       </tr>
       
   343       
       
   344       <?php if ( ($field = getConfig('yms_claim_auth_field', '')) && getConfig('yms_claim_auth_url') ): ?>
       
   345       <!-- Custom field -->
       
   346       <tr>
       
   347         <td class="row2">
       
   348           <?php echo htmlspecialchars($field); ?>
       
   349         </td>
       
   350         <td class="row1">
       
   351           <input type="text" name="custom_field" value="" size="30" />
       
   352         </td>
       
   353       </tr>
       
   354       <?php endif; ?>
       
   355       
       
   356       <!-- Submit -->
       
   357       <tr>
       
   358         <th class="subhead" colspan="2">
       
   359           <input type="submit" value="<?php echo $lang->get('yms_btn_addkey_submit'); ?>" />
       
   360         </th>
       
   361       </tr>
       
   362       
       
   363     </table>
       
   364     </div>
       
   365   
       
   366   </form>
       
   367   <?php
       
   368   $output->footer();
       
   369 }
       
   370 
       
   371 // Show the AES secret for a key
       
   372 function page_Special_YMS_ShowAESKey()
       
   373 {
       
   374   global $db, $session, $paths, $template, $plugins; // Common objects
       
   375   global $lang, $output;
       
   376   
       
   377   $id = intval($paths->getParam(1));
       
   378   
       
   379   // verify ownership, retrieve key
       
   380   $q = $db->sql_query('SELECT client_id, public_id, aes_secret FROM ' . table_prefix . "yms_yubikeys WHERE id = $id;");
       
   381   if ( !$q )
       
   382     $db->_die();
       
   383   
       
   384   if ( $db->numrows() < 1 )
       
   385   {
       
   386     die_friendly('no rows', '<p>key not found</p>');
       
   387   }
       
   388   
       
   389   list($client_id, $public_id, $secret) = $db->fetchrow_num();
       
   390   $db->free_result();
       
   391   
       
   392   if ( $client_id !== $session->user_id )
       
   393     die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('etc_access_denied') . '</p>');
       
   394   
       
   395   $output->header();
       
   396   ?>
       
   397   <div class="tblholder">
       
   398   <table border="0" cellspacing="1" cellpadding="4">
       
   399     <tr>
       
   400       <th colspan="2">
       
   401       <?php echo $lang->get('yms_showaes_th', array('public_id' => yms_modhex_encode($public_id))); ?>
       
   402       </th>
       
   403     </tr>
       
   404     
       
   405     <!-- hex -->
       
   406     <tr>
       
   407       <td class="row2" style="width: 50%;">
       
   408         <?php echo $lang->get('yms_showaes_lbl_hex'); ?>
       
   409       </td>
       
   410       <td class="row1">
       
   411         <?php echo $secret; ?>
       
   412       </td>
       
   413     </tr>
       
   414     
       
   415     <!-- modhex -->
       
   416     <tr>
       
   417       <td class="row2">
       
   418         <?php echo $lang->get('yms_showaes_lbl_modhex'); ?>
       
   419       </td>
       
   420       <td class="row1">
       
   421         <?php echo yms_modhex_encode($secret); ?>
       
   422       </td>
       
   423     </tr>
       
   424     
       
   425     <!-- base64 -->
       
   426     <tr>
       
   427       <td class="row2">
       
   428         <?php echo $lang->get('yms_showaes_lbl_base64'); ?>
       
   429       </td>
       
   430       <td class="row1">
       
   431         <?php echo base64_encode(yms_tobinary($secret)); ?>
       
   432       </td>
       
   433     </tr>
       
   434     
       
   435   </table>
       
   436   </div>
       
   437   <?php
       
   438   $output->footer();
       
   439 }
       
   440 
       
   441 // show the user's API key and client ID
       
   442 function page_Special_YMS_ShowClientInfo()
       
   443 {
       
   444   global $db, $session, $paths, $template, $plugins; // Common objects
       
   445   global $lang, $output;
       
   446   
       
   447   $q = $db->sql_query('SELECT apikey FROM ' . table_prefix . "yms_clients WHERE id = {$session->user_id};");
       
   448   if ( !$q )
       
   449     $db->_die();
       
   450   
       
   451   list($api_key) = $db->fetchrow_num();
       
   452   $db->free_result();
       
   453   
       
   454   $api_key = yms_tobinary($api_key);
       
   455   
       
   456   $output->header();
       
   457   ?>
       
   458   <div class="tblholder">
       
   459   <table border="0" cellspacing="1" cellpadding="4">
       
   460   
       
   461     <tr>
       
   462       <th colspan="2"><?php echo $lang->get('yms_th_client_id'); ?></th>
       
   463     </tr>
       
   464     
       
   465     <tr>
       
   466       <td class="row2"><?php echo $lang->get('yms_lbl_client_id'); ?></td>
       
   467       <td class="row1"><?php echo strval($session->user_id); ?></td>
       
   468     </tr>
       
   469     
       
   470     <tr>
       
   471       <th colspan="2"><?php echo $lang->get('yms_th_api_key'); ?></th>
       
   472     </tr>
       
   473     
       
   474     <tr>
       
   475       <td class="row2"><?php echo $lang->get('yms_showaes_lbl_hex'); ?></td>
       
   476       <td class="row1"><?php echo yms_hex_encode($api_key); ?></td>
       
   477     </tr>
       
   478     
       
   479     <tr>
       
   480       <td class="row2"><?php echo $lang->get('yms_showaes_lbl_modhex'); ?></td>
       
   481       <td class="row1"><?php echo yms_modhex_encode($api_key); ?></td>
       
   482     </tr>
       
   483     
       
   484     <tr>
       
   485       <td class="row2"><?php echo $lang->get('yms_showaes_lbl_base64'); ?></td>
       
   486       <td class="row1"><?php echo base64_encode($api_key); ?></td>
       
   487     </tr>
       
   488   
       
   489   </table>
       
   490   </div>
       
   491   <?php
       
   492   $output->footer();
       
   493 }
       
   494 
       
   495 // Converter between different binary encodings
       
   496 function page_Special_YMS_Converter()
       
   497 {
       
   498   global $db, $session, $paths, $template, $plugins; // Common objects
       
   499   global $lang, $output;
       
   500   
       
   501   $output->header();
       
   502   
       
   503   if ( isset($_POST['value']) )
       
   504   {
       
   505     switch($_POST['format'])
       
   506     {
       
   507       case 'auto':
       
   508       default:
       
   509         $binary = yms_tobinary($_POST['value']);
       
   510         break;
       
   511       case 'hex':
       
   512         $_POST['value'] = str_replace(" ", '', $_POST['value']);
       
   513         $binary = yms_hex_decode($_POST['value']);
       
   514         break;
       
   515       case 'modhex':
       
   516         $binary = yms_hex_decode(yms_modhex_decode($_POST['value']));
       
   517         break;
       
   518       case 'base64':
       
   519         $binary = base64_decode($_POST['value']);
       
   520         break;
       
   521     }
       
   522     
       
   523     if ( empty($binary) )
       
   524     {
       
   525       echo '<div class="error-box">' . $lang->get('yms_conv_err_invalid_string') . '</div>';
       
   526     }
       
   527     else
       
   528     {
       
   529     ?>
       
   530     <div class="tblholder">
       
   531     <table border="0" cellspacing="1" cellpadding="4">
       
   532     
       
   533       <tr>
       
   534         <th colspan="2"><?php echo $lang->get('yms_th_converted_value'); ?></th>
       
   535       </tr>
       
   536       
       
   537       <tr>
       
   538         <td class="row2"><?php echo $lang->get('yms_showaes_lbl_hex'); ?></td>
       
   539         <td class="row1"><?php echo yms_hex_encode($binary); ?></td>
       
   540       </tr>
       
   541       
       
   542       <tr>
       
   543         <td class="row2"><?php echo $lang->get('yms_showaes_lbl_modhex'); ?></td>
       
   544         <td class="row1"><?php echo yms_modhex_encode($binary); ?></td>
       
   545       </tr>
       
   546       
       
   547       <tr>
       
   548         <td class="row2"><?php echo $lang->get('yms_showaes_lbl_base64'); ?></td>
       
   549         <td class="row1"><?php echo base64_encode($binary); ?></td>
       
   550       </tr>
       
   551     
       
   552     </table>
       
   553     </div>
       
   554     <?php
       
   555     }
       
   556   }
       
   557   
       
   558   ?>
       
   559   <form method="post" class="submit_to_self" action="<?php echo makeUrl($paths->fullpage); ?>">
       
   560   
       
   561   <div class="tblholder">
       
   562   <table border="0" cellspacing="1" cellpadding="4">
       
   563   
       
   564     <tr>
       
   565       <th colspan="2"><?php echo $lang->get('yms_th_converter'); ?></th>
       
   566     </tr>
       
   567     
       
   568     <tr>
       
   569       <td class="row2" style="width: 30%;"><?php echo $lang->get('yms_conv_lbl_value'); ?></td>
       
   570       <td class="row1"><input type="text" name="value" size="60" /></td>
       
   571     </tr>
       
   572     
       
   573     <tr>
       
   574       <td class="row2" style="width: 30%;"><?php echo $lang->get('yms_conv_lbl_format'); ?></td>
       
   575       <td class="row1">
       
   576         <?php
       
   577         foreach ( array('auto', 'hex', 'modhex', 'base64') as $i => $fmt )
       
   578         {
       
   579           echo '<label><input type="radio" name="format" value="' . $fmt . '" ';
       
   580           if ( ( isset($_POST['format']) && $_POST['format'] === $fmt ) || ( !isset($_POST['format']) && $i == 0 ) )
       
   581             echo 'checked="checked" ';
       
   582           
       
   583           echo '/> ';
       
   584           echo $lang->get("yms_conv_lbl_format_$fmt"); 
       
   585           echo "</label>\n        ";
       
   586         }
       
   587         ?>
       
   588       </td>
       
   589     </tr>
       
   590     
       
   591     <tr>
       
   592       <th class="subhead" colspan="2">
       
   593         <input type="submit" value="<?php echo $lang->get('yms_conv_btn_submit'); ?>" />
       
   594       </th>
       
   595     </tr>
       
   596   
       
   597   </table>
       
   598   </div>
       
   599   
       
   600   </form>
       
   601   <?php
       
   602   
       
   603   $output->footer();
       
   604 }
       
   605 
       
   606 function page_Special_YMS_AjaxToggleState()
       
   607 {
       
   608   global $db, $session, $paths, $template, $plugins; // Common objects
       
   609   
       
   610   $id = intval($_POST['id']);
       
   611   if ( $_POST['state'] === 'active' )
       
   612     $expr = 'flags | ' . YMS_ENABLED;
       
   613   else
       
   614     $expr = 'flags & ~' . YMS_ENABLED;
       
   615     
       
   616   $q = $db->sql_query('UPDATE ' . table_prefix . "yms_yubikeys SET flags = $expr WHERE id = $id AND client_id = {$session->user_id};");
       
   617   if ( !$q )
       
   618     $db->die_json();
       
   619   
       
   620   if ( $db->sql_affectedrows() < 1 )
       
   621     echo 'no affected rows; not ';
       
   622   
       
   623   echo 'ok';
       
   624 }
       
   625 
       
   626 function page_Special_YMS_AjaxNotes()
       
   627 {
       
   628   global $db, $session, $paths, $template, $plugins; // Common objects
       
   629   
       
   630   if ( isset($_POST['get']) )
       
   631   {
       
   632     $id = intval($_POST['get']);
       
   633     $q = $db->sql_query('SELECT notes FROM ' . table_prefix . "yms_yubikeys WHERE id = $id AND client_id = {$session->user_id};");
       
   634     if ( !$q )
       
   635       $db->_die();
       
   636     if ( $db->numrows() < 1 )
       
   637     {
       
   638       echo "key not found";
       
   639     }
       
   640     else
       
   641     {
       
   642       list($note) = $db->fetchrow_num();
       
   643       echo $note;
       
   644     }
       
   645     $db->free_result();
       
   646   }
       
   647   else if ( isset($_POST['save']) )
       
   648   {
       
   649     $id = intval($_POST['save']);
       
   650     $note = trim($_POST['note']);
       
   651     $note = $db->escape($note);
       
   652     $q = $db->sql_query('UPDATE ' . table_prefix . "yms_yubikeys SET notes = '$note' WHERE id = $id AND client_id = {$session->user_id};");
       
   653     if ( !$q )
       
   654       $db->die_json();
       
   655     
       
   656     echo 'ok';
       
   657   }
       
   658 }
       
   659 
       
   660 // Add key, using just an OTP
       
   661 // Requires the key to be in the database as client ID 0
       
   662 
       
   663 // Client creation
       
   664 function page_Special_YMSCreateClient()
       
   665 {
       
   666   global $db, $session, $paths, $template, $plugins; // Common objects
       
   667   global $lang;
       
   668   global $output;
       
   669   
       
   670   // Require re-auth?
       
   671   if ( $session->auth_level < USER_LEVEL_CHPREF && getConfig('yms_require_reauth', 1) == 1 )
       
   672   {
       
   673     redirect(makeUrlNS('Special', "Login/$paths->fullpage", 'level=' . USER_LEVEL_CHPREF), '', '', 0);
       
   674   }
       
   675   
       
   676   // Check for Yubikey plugin
       
   677   if ( !function_exists('yubikey_validate_otp') )
       
   678   {
       
   679     die_friendly($lang->get('yms_err_yubikey_plugin_missing_title'), '<p>' . $lang->get('yms_err_yubikey_plugin_missing_body') . '</p>');
       
   680   }
       
   681   
       
   682   // Does the client exist?
       
   683   $q = $db->sql_query('SELECT 1 FROM ' . table_prefix . "yms_clients WHERE id = {$session->user_id};");
       
   684   if ( !$q )
       
   685     $db->_die();
       
   686   
       
   687   $client_exists = $db->numrows();
       
   688   $db->free_result();
       
   689   
       
   690   if ( $client_exists )
       
   691   {
       
   692     die_friendly($lang->get('yms_err_client_exists_title'), '<p>' . $lang->get('yms_err_client_exists_body') . '</p>');
       
   693   }
       
   694   
       
   695   $template->add_header('<link rel="stylesheet" type="text/css" href="' . scriptPath . '/plugins/yms/styles.css" />');
       
   696   $output->header();
       
   697   
       
   698   if ( isset($_POST['register_client']) )
       
   699   {
       
   700     // register the client
       
   701     // SHA1 key length: 160 bits
       
   702     $api_key = base64_encode(AESCrypt::randkey(160 / 8));
       
   703     $client_id = $session->user_id;
       
   704     
       
   705     $q = $db->sql_query('INSERT INTO ' . table_prefix . "yms_clients(id, apikey) VALUES ($client_id, '$api_key');");
       
   706     if ( !$q )
       
   707       $db->_die();
       
   708     
       
   709     $validate_url = makeUrlComplete('Special', 'YubikeyValidate');
       
   710     $validate_url = preg_replace('/[?&]auth=[0-9a-f]+/', '', $validate_url);
       
   711     
       
   712     ?>
       
   713     <h3><?php echo $lang->get('yms_register_msg_success_title'); ?></h3>
       
   714     <?php echo $lang->get('yms_register_msg_success_body', array(
       
   715         'yms_link' => makeUrlNS('Special', 'YMS'),
       
   716         'client_id' => $client_id,
       
   717         'api_key' => $api_key,
       
   718         'validate_url' => $validate_url
       
   719       ));
       
   720   }
       
   721   else
       
   722   {
       
   723     // confirmation page
       
   724     ?>
       
   725     <form action="<?php echo makeUrlNS('Special', 'YMSCreateClient'); ?>" method="post">
       
   726       <h3><?php echo $lang->get('yms_register_confirm_title'); ?></h3>
       
   727       <p><?php echo $lang->get('yms_register_confirm_body'); ?></p>
       
   728       <p>
       
   729         <input type="submit" style="font-weight: bold;" name="register_client" value="<?php echo $lang->get('yms_register_btn_submit'); ?>" />
       
   730         <input type="submit" name="cancel" value="<?php echo $lang->get('etc_cancel'); ?>" />
       
   731       </p>
       
   732     </form>
       
   733     <?php
       
   734   }
       
   735   
       
   736   $output->footer();
       
   737 }
       
   738 
       
   739 // Generic response function
       
   740 // Processing functions return either true or a string containing an error message. This
       
   741 // takes that return, and sends a response through the appropriate channel, while allowing
       
   742 // shared backend functions.
       
   743 
       
   744 function yms_send_response($success_string, $result)
       
   745 {
       
   746   global $lang, $output;
       
   747   
       
   748   if ( $result === true )
       
   749   {
       
   750     if ( isset($_GET['ajax']) )
       
   751     {
       
   752       yms_json_response(array(
       
   753         'mode' => 'success',
       
   754         'message' => $lang->get($success_string)
       
   755       ));
       
   756     }
       
   757     else
       
   758     {
       
   759       $output->add_after_header(
       
   760           '<div class="info-box">' . $lang->get($success_string) . '</div>'
       
   761         );
       
   762     }
       
   763   }
       
   764   else
       
   765   {
       
   766     if ( isset($_GET['ajax']) )
       
   767     {
       
   768       yms_json_response(array(
       
   769         'mode' => 'error',
       
   770         'error' => $lang->get($result)
       
   771       ));
       
   772     }
       
   773     else
       
   774     {
       
   775       $output->add_after_header(
       
   776           '<div class="error-box">' . $lang->get($result) . '</div>'
       
   777         );
       
   778     }
       
   779   }
       
   780 }
       
   781 
       
   782 function yms_json_response($response)
       
   783 {
       
   784   global $db, $session, $paths, $template, $plugins; // Common objects
       
   785   
       
   786   header('Content-type: application/json');
       
   787   echo enano_json_encode($response);
       
   788   
       
   789   $db->close();
       
   790   exit;
       
   791 }
       
   792 
       
   793 function yms_date($ts)
       
   794 {
       
   795   return enano_date('Y-m-d H:m:i', $ts);
       
   796 }
       
   797 
       
   798 function yms_state_indicator($flags, $id)
       
   799 {
       
   800   global $lang;
       
   801   return $flags & YMS_ENABLED ?
       
   802     '<span onclick="yms_toggle_state(this, ' . $id . ');" class="yms-enabled">' . $lang->get('yms_state_active') . '</span>' :
       
   803     '<span onclick="yms_toggle_state(this, ' . $id . ');" class="yms-disabled">' . $lang->get('yms_state_inactive') . '</span>';
       
   804 }
       
   805 
       
   806 function yms_notes_cell($notes, $id)
       
   807 {
       
   808   global $lang;
       
   809   $notes = trim($notes);
       
   810   if ( empty($notes) )
       
   811   {
       
   812     $img = 'note_delete.png';
       
   813     $str = $lang->get('yms_btn_note_create');
       
   814   }
       
   815   else
       
   816   {
       
   817     $img = 'note.png';
       
   818     $str = $lang->get('yms_btn_note_view');
       
   819   }
       
   820   echo '<a href="#" onclick="yms_show_notes(this, '.$id.'); return false;" title="' . $str . '"><img alt="' . $str . '" src="' . scriptPath . '/plugins/yms/icons/' . $img . '" /></a>';
       
   821   
       
   822   if ( !empty($notes) )
       
   823   {
       
   824     echo ' ';
       
   825     if ( strlen($notes) > 15 )
       
   826       echo htmlspecialchars(substr($notes, 0, 12)) . '...';
       
   827     else
       
   828       echo htmlspecialchars($notes);
       
   829   }
       
   830 }
       
   831 
       
   832 function yms_show_actions($row)
       
   833 {
       
   834   global $lang;
       
   835   
       
   836   // Show AES secret
       
   837   ?>
       
   838     <a href="<?php echo makeUrlNS('Special', "YMS/ShowAESKey/{$row['id']}"); ?>" title="<?php echo $lang->get('yms_btn_show_aes'); ?>" onclick="yms_showpage('ShowAESKey/<?php echo $row['id']; ?>'); return false;">
       
   839       <img alt="<?php echo $lang->get('yms_btn_show_aes'); ?>" src="<?php echo scriptPath; ?>/plugins/yms/icons/key_go.png" />
       
   840     </a>
       
   841   <?php
       
   842 }