*** /tmp/dacs/dacs-1.4.35/src/auth_token.c	Mon Aug 24 15:50:16 2015
--- auth_token.c	Sun Sep  6 12:30:23 2015
***************
*** 54,59 ****
--- 54,60 ----
    char *item_type;
    char *username;
    char *serial;
+   Auth_key_encoding key_encoding;
    char *key_str;
    unsigned char *key;
    unsigned int keylen;
***************
*** 1489,1494 ****
--- 1490,1496 ----
    tp->item_type = NULL;
    tp->username = NULL;
    tp->serial = NULL;
+   tp->key_encoding = AUTH_KEY_ENCODING_DEFAULT;
    tp->key_str = NULL;
    tp->key = NULL;
    tp->keylen = 0;
***************
*** 1535,1553 ****
    if (tp->serial != NULL)
  	token->serial = strdup(tp->serial);
  
! #ifdef NOTDEF
!   if ((token->key = strhextob(tp->key_str, &token->keylen)) == NULL) {
! 	log_msg((LOG_ERROR_LEVEL, "Decoding hex key failed"));
! 	return(NULL);
!   }
! #endif
    if (tp->key == NULL) {
! 	log_msg((LOG_ERROR_LEVEL, "Internal error: no key is available"));
! 	return(NULL);
    }
    token->key = tp->key;
    token->keylen = tp->keylen;
  
    if (tp->pin != NULL) {
  	if ((token->pin_hash = make_pin_hash(tp->pin)) == NULL)
  	  return(NULL);
--- 1537,1582 ----
    if (tp->serial != NULL)
  	token->serial = strdup(tp->serial);
  
!   /*
!    * If not provided, convert the key string from the indicated format
!    * to binary.
!    */
    if (tp->key == NULL) {
! 	if (tp->key_str == NULL) {
! 	  log_msg((LOG_ERROR_LEVEL, "No hex key string was found"));
! 	  return(NULL);
! 	}
! 
! 	if (tp->key_encoding == AUTH_KEY_ENCODING_HEX) {
! 	  if ((tp->key = strhextob(tp->key_str, &tp->keylen)) == NULL) {
! 		log_msg((LOG_ERROR_LEVEL, "Invalid hex key"));
! 		return(NULL);
! 	  }
! 	}
! 	else if (tp->key_encoding == AUTH_KEY_ENCODING_BASE32) {
! 	  if ((tp->key = stra32b(tp->key_str, NULL, &tp->keylen)) == NULL) {
! 		log_msg((LOG_ERROR_LEVEL, "Invalid base-32 key"));
! 		return(NULL);
! 	  }
! 	}
! 	else if (tp->key_encoding == AUTH_KEY_ENCODING_NONE) {
! 	  tp->key = (unsigned char *) strdup(tp->key_str);
! 	  tp->keylen = strlen((char *) tp->key_str);
! 	}
! 	else {
! 	  log_msg((LOG_ERROR_LEVEL, "Internal error: unrecognized key encoding"));
! 	  return(NULL);
! 	}
    }
+ 
    token->key = tp->key;
    token->keylen = tp->keylen;
  
+   if (token->key == NULL || token->keylen == 0) {
+ 	log_msg((LOG_ERROR_LEVEL, "Invalid hex key found"));
+ 	return(NULL);
+   }
+ 
    if (tp->pin != NULL) {
  	if ((token->pin_hash = make_pin_hash(tp->pin)) == NULL)
  	  return(NULL);
***************
*** 1841,1847 ****
  
    /* We only need to keep the most recent values to match. */
    hbufs = ALLOC_N(char *, TOKEN_HOTP_SYNC_OTPS);
!   
    /* Prime the pump... */
    for (i = 0; i < TOKEN_HOTP_SYNC_OTPS; i++) {
  	if (i != 0)
--- 1870,1876 ----
  
    /* We only need to keep the most recent values to match. */
    hbufs = ALLOC_N(char *, TOKEN_HOTP_SYNC_OTPS);
! 
    /* Prime the pump... */
    for (i = 0; i < TOKEN_HOTP_SYNC_OTPS; i++) {
  	if (i != 0)
***************
*** 1942,1948 ****
    Auth_token *token;
  
    if ((token = auth_token_get(item_type, username)) == NULL) {
! 	*errmsg = ds_xprintf("Cannot find username: \"%s\"", username);
  	return(-1);
    }
  
--- 1971,1977 ----
    Auth_token *token;
  
    if ((token = auth_token_get(item_type, username)) == NULL) {
! 	*errmsg = ds_xprintf("Cannot find token for username: \"%s\"", username);
  	return(-1);
    }
  
***************
*** 2777,2782 ****
--- 2806,2812 ----
  static int
  auth_token_demo_create(Auth_token_param *param)
  {
+   char *url, *url2;
    Auth_token *token;
    Ds *ds;
  
***************
*** 2789,2802 ****
    ds = token_to_xml(token);
    log_msg((LOG_TRACE_LEVEL, "Create demo account:\n%s", ds_buf(ds)));
  
!   printf("<b>An account has been created for username <tt>%s</tt></b>:\n",
! 		 token->username);
!   printf("<blockquote><tt>%s</tt></blockquote>\n",
! 		 xml_escape_cdata(ds_buf(ds)));
  
!   printf("<p>You have %sassigned a PIN to this account.\n",
  		 (token->pin_hash == NULL) ? "<b>not</b> " : "");
  
    printf("<p><b>To continue,</b> ");
    printf("<a href=\"javascript:history.back()\">return to the demo page</a>.\n");
  
--- 2819,2849 ----
    ds = token_to_xml(token);
    log_msg((LOG_TRACE_LEVEL, "Create demo account:\n%s", ds_buf(ds)));
  
!   printf("<b>An account has been created</b>.<br>\n");
!   printf("<b>Demo username</b>: %s:\n", token->username);
! 
!   printf("<p>You selected a <b>%s</b> mode device.<br>\n",
! 		 (token->mode == TOKEN_MODE_COUNTER) ? "HOTP" : "TOTP");
  
!   printf("You have %sassigned a PIN to this account.<br>\n",
  		 (token->pin_hash == NULL) ? "<b>not</b> " : "");
  
+   printf("<p>XML representation</b>:<br><blockquote><tt>%s</tt></blockquote></p>\n",
+ 		 xml_escape_cdata(ds_buf(ds)));
+ 
+   url = ds_xprintf("otpauth://%s/DACS-demo:%s?secret=%s&issuer=DACS-demo",
+ 				   (token->mode == TOKEN_MODE_COUNTER) ? "hotp" : "totp",
+ 				   token->username, param->key_str);
+ 
+   printf("<p><b>URL</b>: <a href=\"%s\">%s</a></p>\n", url, url);
+ 
+   /*
+    * See:
+    * http://www.webmaster-source.com/2010/10/11/generate-qr-codes-on-the-fly-with-the-google-chart-api/
+    */
+   url2 = ds_xprintf("http://chart.apis.google.com/chart?cht=qr&chs=200x200&choe=UTF-8&chld=H&chl=%s", url);
+   printf("<img src=\"%s\">\n", url2);
+ 
    printf("<p><b>To continue,</b> ");
    printf("<a href=\"javascript:history.back()\">return to the demo page</a>.\n");
  
***************
*** 2937,2942 ****
--- 2984,2990 ----
    if (op == TOKEN_OP_DEMO_CREATE) {
  	unsigned int base, ndigits;
  	char *key_str, *p, *serial_str;
+ 	char *key_encoding_str;
  	Auth_token_param param;
  	Auth_hotp_param hotp_param;
  	Auth_totp_param totp_param;
***************
*** 2987,2992 ****
--- 3035,3056 ----
  	  goto demo_failed;
  	}
  
+ 	key_encoding_str = kwv_lookup_value(kwv, "KEY_ENCODING");
+ 	if (key_encoding_str == NULL) {
+ 	  *errmsg = "The KEY_ENCODING argument is required";
+ 	  goto demo_failed;
+ 	}
+ 	if (strcaseeq(key_encoding_str, "Hex"))
+ 	  param.key_encoding = AUTH_KEY_ENCODING_HEX;
+ 	else if (strcaseeq(key_encoding_str, "base32"))
+ 	  param.key_encoding = AUTH_KEY_ENCODING_BASE32;
+ 	else if (strcaseeq(key_encoding_str, "none"))
+ 	  param.key_encoding = AUTH_KEY_ENCODING_NONE;
+ 	else {
+ 	  *errmsg = "Unrecognized KEY_ENCODING argument";
+ 	  goto demo_failed;
+ 	}
+ 
  	if ((p = kwv_lookup_value(kwv, "NDIGITS")) != NULL) {
  	  if (strnum(p, STRNUM_UI, &ndigits) == -1
  		  || ndigits < TOKEN_MIN_NDIGITS || ndigits > TOKEN_MAX_NDIGITS) {
***************
*** 3082,3088 ****
    }
  
    if (username == NULL || pw_check_username(username) == -1) {
!     *errmsg = "Invalid USERNAME argument";
  	if (is_demo)
  	  goto demo_failed;
      return(-1);
--- 3146,3152 ----
    }
  
    if (username == NULL || pw_check_username(username) == -1) {
!     *errmsg = "Missing or invalid USERNAME argument";
  	if (is_demo)
  	  goto demo_failed;
      return(-1);
