yms/yms.php
changeset 11 b9eb748ac1e4
parent 9 d58bafde2a92
equal deleted inserted replaced
10:351d40b21cbc 11:b9eb748ac1e4
   101       $enabled = true;
   101       $enabled = true;
   102     }
   102     }
   103     
   103     
   104     $result = yms_add_yubikey($_POST['add_aes'], $_POST['add_otp'], $client_id, $enabled, $any_client, $notes);
   104     $result = yms_add_yubikey($_POST['add_aes'], $_POST['add_otp'], $client_id, $enabled, $any_client, $notes);
   105     yms_send_response('yms_msg_addkey_success', $result);
   105     yms_send_response('yms_msg_addkey_success', $result);
       
   106   }
       
   107   else if ( isset($_POST['csv']) )
       
   108   {
       
   109     $csv = explode("\n", trim($_POST['csv']));
       
   110     
       
   111     $errors = array();
       
   112     
       
   113     // first line: header
       
   114     $head = str_getcsv($csv[0]);
       
   115     
       
   116     // column check: aes_secret
       
   117     if ( !in_array('aes_secret', $head) )
       
   118     {
       
   119       $errors[] = $lang->get('yms_err_add_batch_missing_aes_key');
       
   120     }
       
   121     
       
   122     // column check: otp, public_id and private_id
       
   123     if ( !in_array('otp', $head) )
       
   124     {
       
   125       if ( !in_array('public_id', $head) || !in_array('private_id', $head) )
       
   126       {
       
   127         $errors[] = $lang->get('yms_err_add_batch_missing_id');
       
   128       }
       
   129     }
       
   130     
       
   131     if ( !empty($errors) )
       
   132     {
       
   133       yms_send_response(false, '<ul><li>' . implode('</li><li>', $errors) . '</li></ul>');
       
   134     }
       
   135     
       
   136     // we are good to start processing
       
   137     $db->transaction_begin();
       
   138     for ( $i = 1; $i < count($csv); $i++ )
       
   139     {
       
   140       $line = str_getcsv($csv[$i]);
       
   141       
       
   142       // ensure column count == row count
       
   143       if ( count($line) !== count($head) )
       
   144       {
       
   145         $errors[] = $lang->get('yms_err_add_batch_bad_row_count', array('line' => $i));
       
   146         continue;
       
   147       }
       
   148       
       
   149       // remap line
       
   150       foreach ( $head as $j => $col )
       
   151       {
       
   152         $line[$col] =& $line[$j];
       
   153       }
       
   154       
       
   155       // initialize row
       
   156       $row = array(
       
   157         'client_id' => $yms_client_id,
       
   158         'aes_secret' => yms_hex_encode(yms_tobinary($line['aes_secret'])),
       
   159         'session_count' => 0,
       
   160         'token_count' => 0,
       
   161         'create_time' => time(),
       
   162         'token_time' => 0,
       
   163         'flags' => 0,
       
   164         'notes' => ''
       
   165       );
       
   166       
       
   167       if ( !preg_match('/^[0-9a-f]{32}$/', $row['aes_secret']) )
       
   168       {
       
   169         $errors[] = $lang->get('yms_err_add_batch_aes_secret', array('line' => $i));
       
   170         continue;
       
   171       }
       
   172       
       
   173       // do we have an OTP?
       
   174       if ( isset($line['otp']) )
       
   175       {
       
   176         // yes, decode it
       
   177         $otp = yms_decode_otp($line['otp'], $line['aes_secret']);
       
   178         if ( $otp === false )
       
   179         {
       
   180           $errors[] = $lang->get('yms_err_add_batch_bad_otp', array('line' => $i));
       
   181           continue;
       
   182         }
       
   183         
       
   184         if ( !$otp['crc_good'] )
       
   185         {
       
   186           $errors[] = $lang->get('yms_err_add_batch_bad_otp', array('line' => $i));
       
   187           continue;
       
   188         }
       
   189        
       
   190         $row['public_id'] = $otp['publicid'];
       
   191         $row['private_id'] = $otp['privateid'];
       
   192         $row['session_count'] = $otp['session'];
       
   193         $row['token_count'] = $otp['count'];
       
   194         $row['token_time'] = $otp['timestamp'];
       
   195       }
       
   196       
       
   197       // public and private ID
       
   198       foreach ( array('public_id', 'private_id') as $col )
       
   199       {
       
   200         if ( !empty($line[$col]) )
       
   201         {
       
   202           $row[$col] = yms_hex_encode(yms_tobinary($line[$col]));
       
   203         }
       
   204         if ( !isset($row[$col]) || !preg_match('/^[0-9a-f]{12}$/', $row[$col]) )
       
   205         {
       
   206           $errors[] = $lang->get("yms_err_add_batch_bad_$col", array('line' => $i));
       
   207           continue 2;
       
   208         }
       
   209       }
       
   210       
       
   211       // session count, token count and timestamp
       
   212       foreach ( array('session_count', 'token_count', 'token_time') as $col )
       
   213       {
       
   214         if ( !empty($line[$col]) )
       
   215         {
       
   216           $row[$col] = intval($line[$col]);
       
   217         }
       
   218       }
       
   219       
       
   220       // notes
       
   221       if ( isset($line['notes']) )
       
   222       {
       
   223         $row['notes'] = trim($line['notes']);
       
   224       }
       
   225       
       
   226       // lifecycle state
       
   227       if ( isset($line['lifecycle_state']) )
       
   228       {
       
   229         if ( !in_array($line['lifecycle_state'], array('active', 'inactive')) )
       
   230         {
       
   231           $errors[] = $lang->get('yms_err_add_batch_bad_lifecycle_state', array('line' => $i));
       
   232           continue;
       
   233         }
       
   234         
       
   235         if ( $line['lifecycle_state'] === 'active' )
       
   236         {
       
   237           $row['flags'] |= YMS_ENABLED;
       
   238         }
       
   239       }
       
   240       else
       
   241       {
       
   242         // default to active
       
   243         $row['flags'] |= YMS_ENABLED;
       
   244       }
       
   245       
       
   246       // global access
       
   247       if ( isset($line['access']) )
       
   248       {
       
   249         if ( !in_array($line['access'], array('global', 'restricted')) )
       
   250         {
       
   251           $errors[] = $lang->get('yms_err_add_batch_bad_access', array('line' => $i));
       
   252           continue;
       
   253         }
       
   254         
       
   255         if ( $line['access'] === 'global' )
       
   256         {
       
   257           $row['flags'] |= YMS_ANY_CLIENT;
       
   258         }
       
   259       }
       
   260       
       
   261       // duplicate key check
       
   262       $q = $db->sql_query('SELECT 1 FROM ' . table_prefix . "yms_yubikeys WHERE public_id = '{$row['public_id']}';");
       
   263       if ( $db->numrows() > 0 )
       
   264       {
       
   265         $errors[] = $lang->get('yms_err_add_batch_duplicate', array('line' => $i, 'public_id' => $row['public_id']));
       
   266         continue;
       
   267       }
       
   268       
       
   269       // build query
       
   270       $cols = implode(', ', array_keys($row));
       
   271       
       
   272       foreach ( $row as &$cell )
       
   273       {
       
   274         if ( is_string($cell) )
       
   275         {
       
   276           $cell = "'" . $db->escape($cell) . "'";
       
   277         }
       
   278       }
       
   279       unset($cell);
       
   280       
       
   281       $query = sprintf("INSERT INTO %syms_yubikeys ( %s ) VALUES ( %s );",
       
   282                        table_prefix,
       
   283                        $cols,
       
   284                        implode(', ', $row)
       
   285                        );
       
   286       
       
   287       // insert it!
       
   288       $q = $db->sql_query($query);
       
   289       if ( $q )
       
   290       {
       
   291         $errors[] = $lang->get('yms_err_add_batch_success', array('line' => $i, 'public_id' => $row['public_id']));
       
   292       }
       
   293       else
       
   294       {
       
   295         $errors[] = $lang->get('yms_err_add_batch_query', array('line' => $i, 'public_id' => $row['public_id'], 'error' => $db->sql_error()));
       
   296       }
       
   297     }
       
   298     $db->transaction_commit();
       
   299     
       
   300     yms_send_response('<p><strong>' . $lang->get('yms_lbl_add_batch_success_head') . '</strong></p><ul><li>' . implode('</li><li>', $errors) . '</li></ul>', true);
   106   }
   301   }
   107   else if ( isset($_POST['claim_otp']) && getConfig('yms_claim_enable', 0) == 1 )
   302   else if ( isset($_POST['claim_otp']) && getConfig('yms_claim_enable', 0) == 1 )
   108   {
   303   {
   109     // do we need to validate a custom field?
   304     // do we need to validate a custom field?
   110     if ( ($url = getConfig('yms_claim_auth_url')) && getConfig('yms_claim_auth_field') && getConfig('yms_claim_auth_enable', 0) == 1 )
   305     if ( ($url = getConfig('yms_claim_auth_url')) && getConfig('yms_claim_auth_field') && getConfig('yms_claim_auth_enable', 0) == 1 )
   174   ?>
   369   ?>
   175   <div class="yms-buttons">
   370   <div class="yms-buttons">
   176     <a class="abutton abutton_green icon" style="background-image: url(<?php echo scriptPath; ?>/plugins/yms/icons/key_add.png);"
   371     <a class="abutton abutton_green icon" style="background-image: url(<?php echo scriptPath; ?>/plugins/yms/icons/key_add.png);"
   177        href="<?php echo makeUrlNS('Special', 'YMS/AddKey'); ?>" onclick="yms_showpage('AddKey'); return false;">
   372        href="<?php echo makeUrlNS('Special', 'YMS/AddKey'); ?>" onclick="yms_showpage('AddKey'); return false;">
   178       <?php echo $lang->get('yms_btn_add_key'); ?>
   373       <?php echo $lang->get('yms_btn_add_key'); ?>
       
   374     </a>
       
   375     <a class="abutton icon" style="background-image: url(<?php echo scriptPath; ?>/plugins/yms/icons/key_add.png);"
       
   376        href="<?php echo makeUrlNS('Special', 'YMS/AddKeyBatch'); ?>" onclick="yms_showpage('AddKeyBatch'); return false;">
       
   377       <?php echo $lang->get('yms_btn_add_batch'); ?>
   179     </a>
   378     </a>
   180     <?php if ( getConfig('yms_claim_enable', 0) == 1 && $yms_client_id > 0 ): ?>
   379     <?php if ( getConfig('yms_claim_enable', 0) == 1 && $yms_client_id > 0 ): ?>
   181     <a class="abutton abutton_blue icon" style="background-image: url(<?php echo scriptPath; ?>/plugins/yms/icons/key_add.png);"
   380     <a class="abutton abutton_blue icon" style="background-image: url(<?php echo scriptPath; ?>/plugins/yms/icons/key_add.png);"
   182        href="<?php echo makeUrlNS('Special', 'YMS/AddPreregisteredKey'); ?>" onclick="yms_showpage('AddPreregisteredKey'); return false;">
   381        href="<?php echo makeUrlNS('Special', 'YMS/AddPreregisteredKey'); ?>" onclick="yms_showpage('AddPreregisteredKey'); return false;">
   183       <?php echo $lang->get('yms_btn_add_key_preregistered'); ?>
   382       <?php echo $lang->get('yms_btn_add_key_preregistered'); ?>
   386   </form>
   585   </form>
   387   <?php
   586   <?php
   388   $output->footer();
   587   $output->footer();
   389 }
   588 }
   390 
   589 
       
   590 // Add multiple Yubikeys by uploading a CSV
       
   591 function page_Special_YMS_AddKeyBatch()
       
   592 {
       
   593   global $db, $session, $paths, $template, $plugins; // Common objects
       
   594   global $lang, $output;
       
   595   
       
   596   $output->add_after_header('<div class="breadcrumbs">
       
   597       <a href="' . makeUrlNS('Special', 'YMS') . '">' . $lang->get('yms_specialpage_yms') . '</a> &raquo;
       
   598       ' . $lang->get('yms_btn_add_batch') . '
       
   599     </div>');
       
   600   
       
   601   $output->header();
       
   602   ?>
       
   603   
       
   604   <h3><?php echo $lang->get('yms_lbl_add_batch_heading'); ?></h3>
       
   605   <?php echo $lang->get('yms_lbl_add_batch_desc'); ?>
       
   606   
       
   607   <form action="<?php echo makeUrlNS('Special', 'YMS'); ?>" method="post">
       
   608   
       
   609   <div class="tblholder">
       
   610     <table border="0" cellspacing="1" cellspacing="4">
       
   611       <!-- CSV paste -->
       
   612       <tr>
       
   613         <td class="row2">
       
   614           <?php echo $lang->get('yms_lbl_add_batch_field_csv'); ?><br />
       
   615           <small><?php echo $lang->get('yms_lbl_add_batch_field_csv_hint'); ?></small>
       
   616         </td>
       
   617         <td class="row1">
       
   618           <textarea name="csv" rows="8" cols="60"></textarea>
       
   619         </td>
       
   620       </tr>
       
   621       
       
   622       <!-- Submit -->
       
   623       <tr>
       
   624         <th class="subhead" colspan="2">
       
   625           <input type="submit" value="<?php echo $lang->get('yms_btn_add_batch_submit'); ?>" />
       
   626         </th>
       
   627       </tr>
       
   628     </table>
       
   629   </div>
       
   630   
       
   631   </form>
       
   632   
       
   633   <?php
       
   634   $output->footer();
       
   635 }
       
   636 
   391 // Add key, using just an OTP
   637 // Add key, using just an OTP
   392 // Requires the key to be in the database as client ID 0
   638 // Requires the key to be in the database as client ID 0
   393 function page_Special_YMS_AddPreregisteredKey()
   639 function page_Special_YMS_AddPreregisteredKey()
   394 {
   640 {
   395   global $db, $session, $paths, $template, $plugins; // Common objects
   641   global $db, $session, $paths, $template, $plugins; // Common objects
   853     
  1099     
   854   $q = $db->sql_query('UPDATE ' . table_prefix . "yms_yubikeys SET flags = $expr WHERE id = $id AND client_id = {$yms_client_id};");
  1100   $q = $db->sql_query('UPDATE ' . table_prefix . "yms_yubikeys SET flags = $expr WHERE id = $id AND client_id = {$yms_client_id};");
   855   if ( !$q )
  1101   if ( !$q )
   856     $db->die_json();
  1102     $db->die_json();
   857   
  1103   
   858   if ( $db->sql_affectedrows() < 1 )
       
   859     echo 'no affected rows; not ';
       
   860   
       
   861   echo 'ok';
  1104   echo 'ok';
   862 }
  1105 }
   863 
  1106 
   864 function page_Special_YMS_AjaxNotes()
  1107 function page_Special_YMS_AjaxNotes()
   865 {
  1108 {