コード例 #1
0
ファイル: util.c プロジェクト: darkshade9/yubico-pam
int
load_chalresp_state(FILE *f, CR_STATE *state, bool verbose)
{
  /*
   * Load the current challenge and expected response information from a file handle.
   *
   * Format is hex(challenge):hex(response):slot num
   */
  char challenge_hex[CR_CHALLENGE_SIZE * 2 + 1], response_hex[CR_RESPONSE_SIZE * 2 + 1];
  int slot;
  int r;

  if (! f)
    goto out;

  /* XXX not ideal with hard coded lengths in this scan string.
   * 126 corresponds to twice the size of CR_CHALLENGE_SIZE,
   * 40 is twice the size of CR_RESPONSE_SIZE
   * (twice because we hex encode the challenge and response)
   */
  r = fscanf(f, "v1:%126[0-9a-z]:%40[0-9a-z]:%d", &challenge_hex[0], &response_hex[0], &slot);
  if (r != 3) {
    D(("Could not parse contents of chalresp_state file (%i)", r));
    goto out;
  }

  if (verbose)
    D(("Challenge: %s, expected response: %s, slot: %d", challenge_hex, response_hex, slot));

  if (! yubikey_hex_p(challenge_hex)) {
    D(("Invalid challenge hex input : %s", challenge_hex));
    goto out;
  }

  if (! yubikey_hex_p(response_hex)) {
    D(("Invalid expected response hex input : %s", response_hex));
    goto out;
  }

  if (slot != 1 && slot != 2) {
    D(("Invalid slot input : %i", slot));
    goto out;
  }

  yubikey_hex_decode(state->challenge, challenge_hex, sizeof(state->challenge));
  state->challenge_len = strlen(challenge_hex) / 2;

  yubikey_hex_decode(state->response, response_hex, sizeof(state->response));
  state->response_len = strlen(response_hex) / 2;

  state->slot = slot;

  return 1;

 out:
  return 0;
}
コード例 #2
0
/**
 * The Modhex encoding is described in Yubikey manual, as a start point You
 * can read this: @link https://www.yubico.com/modhex-calculator/ .
 * @param p2Modhex what to encode.
 * @return input Modhex encoded.
 *
 */
const string YubikoOtpKeyConfig::hex2Modhex(const string& p2Modhex) {
	const unsigned long mySz = p2Modhex.size();
	const unsigned long mySz2 = mySz / 2;
	vector<uint8_t> myBytes(mySz2, uint8_t(0));
	yubikey_hex_decode(reinterpret_cast<char*>(&myBytes[0]), p2Modhex.c_str(),
			mySz);
	string myPubId(mySz + 1, '\0');
	yubikey_modhex_encode(&myPubId[0], reinterpret_cast<char*>(&myBytes[0]),
			mySz2);
	myPubId.resize(mySz);
	return myPubId;
}
コード例 #3
0
int get_entry_from_id(int id, entry_st *entry, sqlite3 *db)
{
  char *request;
  char *uid, *aes;
  int rc;
  sqlite3_stmt *ppStmt;


  request = sqlite3_mprintf("SELECT uid, aes, counter, session FROM tokens WHERE id=%d;", id);

  rc = sqlite3_prepare_v2(db, request, -1,
			  &ppStmt, NULL);
  sqlite3_free(request);
  if(check_error("Error in preparing SELECT", rc, db))
    return CHK_FAIL;

  rc = sqlite3_step(ppStmt);
  if(check_error("Error in SELECT", rc, db))
    return CHK_FAIL;

  if (rc == SQLITE_ROW)
    {
      uid = (char *) sqlite3_column_text(ppStmt, 0);
      //printf("uid: %s\n", uid);
      aes = (char *) sqlite3_column_text(ppStmt, 1);
      //printf("aes: %s\n", aes);
      if ((strlen(uid) != 2*YUBIKEY_UID_SIZE) &&
	  (strlen(aes) != 2*YUBIKEY_KEY_SIZE))
	{
	  sqlite3_finalize(ppStmt);
	  printf("Error in database: wrong uid/aes size\n");
	  return CHK_FAIL;
	}
      strcpy(entry->uid, uid);
      strcpy(entry->aes, aes);

      entry->counter = sqlite3_column_int(ppStmt, 2);
      entry->session = sqlite3_column_int(ppStmt, 3);
      entry->id = id;
      //printf("counter: %d - session: %d\n", entry->counter, entry->session);
      sqlite3_finalize(ppStmt);

      yubikey_hex_decode ((char *) entry->aes_bin,
			  entry->aes, YUBIKEY_KEY_SIZE);
      return CHK_OK;
    }
  else
    {
      sqlite3_finalize(ppStmt);
      return CHK_FAIL;
    }
}
コード例 #4
0
/**
 * Setter.
 *
 * @param pPrivateId Hex-encoded string representing the private id Yubikey token part.
 */
void YubikoOtpKeyConfig::setPrivateId(const string &pPrivateId) {
	BOOST_LOG_NAMED_SCOPE("YubikoOtpKeyConfig::setPrivateId");
	string myPrivateId(pPrivateId);
	trim(myPrivateId);
	if (myPrivateId.size() != K_YBK_PRIVATE_ID_LEN) {
		throw WrongConfigValue(WrongConfigValue::EYbkPrivateId,
				K_YBK_PRIVATE_ID_LEN, myPrivateId);
	}
	if (getPrivateId() != pPrivateId) {
		yubikey_hex_decode(reinterpret_cast<char*>(itsToken.uid),
				myPrivateId.c_str(), YUBIKEY_UID_SIZE);
		itsChangedFlag = true;
	}
}
コード例 #5
0
void YubikoOtpKeyConfig::setSecretKey(const std::string& pKey) {
	BOOST_LOG_NAMED_SCOPE(
			"YubikoOtpKeyConfig::setSecretKey( const std::string& pKey)");
	string mySecretKey(pKey);
	trim(mySecretKey);
	if (mySecretKey.size() != K_SEC_KEY_SZ) {
		throw WrongConfigValue(WrongConfigValue::EYbkSecretKey, K_SEC_KEY_SZ,
				mySecretKey);
	}
	if (getSecretKey() != pKey) {
		yubikey_hex_decode(reinterpret_cast<char*>(itsKey.data()),
				mySecretKey.c_str(),
				YUBIKEY_KEY_SIZE);
		itsChangedFlag = true;
	}
}
コード例 #6
0
ファイル: selftest.c プロジェクト: Yubico/yubico-c-dpkg
static void
hex_test2 (void)
{
  char buf[1024];
  char buf2[1024];

  yubikey_hex_encode (buf, "test", 4);
  printf ("hex-encode(\"test\") = %s\n", buf);
  assert (strcmp (buf, "74657374") == 0);
  printf ("Hex-2.1 success\n");

  printf ("hex-decode(\"%s\") = ", buf);
  yubikey_hex_decode (buf2, buf, sizeof (buf2));
  printf ("%.*s\n", 4, buf2);
  assert (memcmp (buf2, "test", 4) == 0);
  printf ("Hex-2.2 success\n");
}
コード例 #7
0
/* Decode 128 bit AES key into cfg->ykcore_config.key */
int ykp_AES_key_from_hex(YKP_CONFIG *cfg, const char *hexkey) {
	char aesbin[256];

	/* Make sure that the hexkey is exactly 32 characters */
	if (strlen(hexkey) != 32) {
		return 1;  /* Bad AES key */
	}

	/* Make sure that the hexkey is made up of only [0-9a-f] */
	if (! yubikey_hex_p(hexkey))
		return 1;

	yubikey_hex_decode(aesbin, hexkey, sizeof(aesbin));
	memcpy(cfg->ykcore_config.key, aesbin, sizeof(cfg->ykcore_config.key));

	return 0;
}
コード例 #8
0
ファイル: selftest.c プロジェクト: Yubico/yubico-c-dpkg
static void
hex_test5 (void)
{
  char buf[1024];
  char buf2[1024];
  char cmp[1024];

  strcpy (buf, "a2c2a");
  memset (buf2, 0, sizeof (buf2));
  yubikey_hex_decode (buf2, buf, sizeof (buf2));
  printf ("hex-decode(\"%s\") = %x%x%x\n", buf, buf2[0], buf2[1], buf2[2]);
  cmp[0] = 0xa;
  cmp[1] = 0x2c;
  cmp[2] = 0x2a;
  assert (memcmp (buf2, cmp, 3) == 0);
  printf ("Hex-5 success\n");
}
コード例 #9
0
/* Decode 160 bits HMAC key, used with OATH and HMAC challenge-response.
 *
 * The first 128 bits of the HMAC go key into cfg->ykcore_config.key,
 * and 32 bits into the first four bytes of cfg->ykcore_config.uid.
*/
int ykp_HMAC_key_from_hex(YKP_CONFIG *cfg, const char *hexkey) {
	char aesbin[256];
	int i;

	/* Make sure that the hexkey is exactly 40 characters */
	if (strlen(hexkey) != 40) {
		return 1;  /* Bad HMAC key */
	}

	/* Make sure that the hexkey is made up of only [0-9a-f] */
	if (! yubikey_hex_p(hexkey))
		return 1;

	yubikey_hex_decode(aesbin, hexkey, sizeof(aesbin));
	i = sizeof(cfg->ykcore_config.key);
	memcpy(cfg->ykcore_config.key, aesbin, i);
	memcpy(cfg->ykcore_config.uid, aesbin + i, 20 - i);

	return 0;
}
コード例 #10
0
ファイル: ykchalresp.c プロジェクト: jrmithdobbs/sdmckt
int main(int argc, char **argv) {
  char * encoded = "353f962fd41dc45f842be0e0e7888a9e8dba40a4db61bacc92dae628d90e4c4a";
  unsigned char response[20];
  unsigned char decoded[32];
  unsigned int i;

  printf("%s\n",encoded);
  yubikey_hex_decode((char *)decoded, encoded, sizeof(decoded));
  for (i = 0; i < 32; i++) {
    printf("%02x",decoded[i]);
  }
  printf("\n");

  memset(response,0,20);
  if(yubi_hmac_challenge_response(2,(unsigned char *)&decoded,(unsigned char *)&response) == 20) {
    for (i = 0; i < 20; i++) {
      printf("%02x",response[i]);
    }
    printf("\n");
  }
  return 0;
}
コード例 #11
0
static int hex_modhex_decode(unsigned char *result, size_t *resultlen,
			     const char *str, size_t strl,
			     size_t minsize, size_t maxsize,
			     bool primarily_modhex)
{
	if (strl >= 2) {
		if (strncmp(str, "m:", 2) == 0
		    || strncmp(str, "M:", 2) == 0) {
			str += 2;
			strl -= 2;
			primarily_modhex = true;
		} else if (strncmp(str, "h:", 2) == 0
			   || strncmp(str, "H:", 2) == 0) {
			str += 2;
			strl -= 2;
			primarily_modhex = false;
		}
	}

	if ((strl % 2 != 0) || (strl < minsize) || (strl > maxsize)) {
		return -1;
	}

	*resultlen = strl / 2;
	if (primarily_modhex) {
		if (yubikey_modhex_p(str)) {
			yubikey_modhex_decode((char *)result, str, strl);
			return 1;
		}
	} else {
		if (yubikey_hex_p(str)) {
			yubikey_hex_decode((char *)result, str, strl);
			return 1;
		}
	}

	return 0;
}
コード例 #12
0
int YubiKeyUtil::hexModhexDecode(unsigned char *result, size_t *resultLen,
                                 const char *str, size_t strLen,
                                 size_t minSize, size_t maxSize,
                                 bool modhex)
{
    if ((strLen % 2 != 0) || (strLen < minSize) || (strLen > maxSize)) {
        return -1;
    }

    *resultLen = strLen / 2;
    if (modhex) {
        if (yubikey_modhex_p(str)) {
            yubikey_modhex_decode((char *)result, str, strLen);
            return 1;
        }
    } else {
        if (yubikey_hex_p(str)) {
            yubikey_hex_decode((char *)result, str, strLen);
            return 1;
        }
    }

    return 0;
}
コード例 #13
0
ファイル: selftest.c プロジェクト: bgarlock/yubico-c
int
main (void)
{
  char buf[1024];
  size_t i;
  int rc;
  yubikey_token_st tok;


  /* Test Modhex */
  yubikey_modhex_encode (buf, "test", 4);
  printf ("modhex-encode(\"test\") = %s\n", buf);
  if (strcmp (buf, "ifhgieif") != 0)
    {
      printf ("ModHex failure\n");
      return 1;
    }
  printf ("Modhex-1 success\n");

  printf ("modhex-decode(\"%s\") = ", buf);
  yubikey_modhex_decode (buf, buf, strlen ((char *) buf));
  printf ("%.*s\n", 4, buf);
  if (memcmp (buf, "test", 4) != 0)
    {
      printf ("ModHex failure\n");
      return 1;
    }
  printf ("Modhex-2 success\n");

  strcpy (buf, "cbdefghijklnrtuv");
  rc = yubikey_modhex_p (buf);
  printf ("hex-p(\"%s\") = %d\n", buf, rc);
  if (!rc)
    {
      printf ("Hex_p failure\n");
      return 1;
    }
  printf ("Hex-3 success\n");

  strcpy (buf, "0123Xabc");
  rc = yubikey_hex_p (buf);
  printf ("hex-p(\"%s\") = %d\n", buf, rc);
  if (rc)
    {
      printf ("Hex_p failure\n");
      return 1;
    }
  printf ("Hex-3 success\n");

  /* Test Hex */

  yubikey_hex_encode (buf, "test", 4);
  printf ("hex-encode(\"test\") = %s\n", buf);
  if (strcmp (buf, "74657374") != 0)
    {
      printf ("Hex failure\n");
      return 1;
    }
  printf ("Hex-1 success\n");

  printf ("hex-decode(\"%s\") = ", buf);
  yubikey_hex_decode (buf, buf, strlen ((char *) buf));
  printf ("%.*s\n", 4, buf);
  if (memcmp (buf, "test", 4) != 0)
    {
      printf ("Hex failure\n");
      return 1;
    }
  printf ("Hex-2 success\n");

  strcpy (buf, "0123456789abcdef");
  rc = yubikey_hex_p (buf);
  printf ("hex-p(\"%s\") = %d\n", buf, rc);
  if (!rc)
    {
      printf ("Hex_p failure\n");
      return 1;
    }
  printf ("Hex-3 success\n");

  strcpy (buf, "0123Xabc");
  rc = yubikey_hex_p (buf);
  printf ("hex-p(\"%s\") = %d\n", buf, rc);
  if (rc)
    {
      printf ("Hex_p failure\n");
      return 1;
    }
  printf ("Hex-3 success\n");

  /* Test AES */

  {
    uint8_t buf[1024];
    char out[1024];
    uint8_t key[16 + 1];

    memcpy (buf, "0123456789abcdef\0", 17);
    memcpy (key, "abcdef0123456789\0", 17);
    printf ("aes-decrypt (data=%s, key=%s)\n => ", (char *) buf,
	    (char *) key);
    yubikey_aes_decrypt (buf, key);
    for (i = 0; i < 16; i++)
      printf ("%02x", buf[i] & 0xFF);
    printf ("\n");

    if (memcmp (buf,
		"\x83\x8a\x46\x7f\x34\x63\x95\x51"
		"\x75\x5b\xd3\x2a\x4a\x2f\x15\xe1", 16) != 0)
      {
	printf ("AES failure\n");
	return 1;
      }
    printf ("AES-1 success\n");

    yubikey_aes_encrypt (buf, key);
    if (memcmp (buf, "0123456789abcdef", 16) != 0)
      {
	printf ("AES encryption failure\n");
	return 1;
      }
    printf ("AES-2 success\n");

    /* Test OTP */

    memcpy ((void *) &tok,
	    "\x16\xe1\xe5\xd9\xd3\x99\x10\x04\x45\x20\x07\xe3\x02\x00\x00",
	    16);
    memcpy (key, "abcdef0123456789", 16);

    yubikey_generate ((void *) &tok, key, out);
    yubikey_parse ((uint8_t *) out, key, &tok);

    if (memcmp
	(&tok, "\x16\xe1\xe5\xd9\xd3\x99\x10\x04\x45\x20\x07\xe3\x02\x00\x00",
	 16) != 0)
      {
	printf ("OTP generation - parse failure\n");
	return 1;
      }
    printf ("OTP-1 success\n");
  }

  return 0;
}
コード例 #14
0
int main(int argc, char **argv)
{
	YK_KEY *yk = 0;
	bool error = true;
	int exit_code = 0;

	/* Options */
	bool serial_dec = false;
	bool serial_modhex = false;
	bool serial_hex = false;
	bool version = false;
	bool touch_level = false;
	bool pgm_seq = false;
	bool slot1 = false;
	bool slot2 = false;
	bool vid = false;
	bool pid = false;

	bool quiet = false;

	yk_errno = 0;

	if (! parse_args(argc, argv,
				&serial_dec, &serial_modhex, &serial_hex,
				&version, &touch_level, &pgm_seq, &quiet,
				&slot1, &slot2, &vid, &pid,
				&exit_code))
		exit(exit_code);

	if (!yk_init()) {
		exit_code = 1;
		goto err;
	}

	if (!(yk = yk_open_first_key())) {
		exit_code = 1;
		goto err;
	}

	if(serial_dec || serial_modhex || serial_hex) {
		unsigned int serial;
		int ret = yk_get_serial(yk, 1, 0, &serial);
		if(!ret) {
			exit_code = 1;
			goto err;
		}
		if(serial_dec) {
			if(!quiet)
				printf("serial: ");
			printf("%d\n", serial);
		}
		if(serial_modhex || serial_hex) {
			char buf[64];
			char hex_serial[64];
			char modhex_serial[64];
			char *ptr = buf;

			int chars = snprintf(buf + 1, 63, "%x", serial);
			if(chars % 2 == 1) {
				buf[0] = '0';
			} else {
				ptr += 1;
			}
			if(serial_hex) {
				if(!quiet)
					printf("serial_hex: ");
				printf("%s\n", ptr);
			}
			if(serial_modhex) {
				yubikey_hex_decode(hex_serial, ptr, strlen(ptr));
				yubikey_modhex_encode(modhex_serial, hex_serial, strlen(hex_serial));
				if(!quiet)
					printf("serial_modhex: ");
				printf("%s\n", modhex_serial);
			}
		}
	}
	if(version || touch_level || pgm_seq || slot1 || slot2) {
		YK_STATUS *st = ykds_alloc();
		if(!yk_get_status(yk, st)) {
			ykds_free(st);
			exit_code = 1;
			goto err;
		}

		if(version) {
			if(!quiet)
				printf("version: ");
			printf("%d.%d.%d\n", ykds_version_major(st), ykds_version_minor(st), ykds_version_build(st));
		}
		if(touch_level) {
			if(!quiet)
				printf("touch_level: ");
			printf("%d\n", ykds_touch_level(st));
		}
		if(pgm_seq) {
			if(!quiet)
				printf("programming_sequence: ");
			printf("%d\n", ykds_pgm_seq(st));
		}
		if(slot1) {
			if(!quiet)
				printf("slot1_status: ");
			printf("%d\n", (ykds_touch_level(st) & CONFIG1_VALID) == CONFIG1_VALID);
		}
		if(slot2) {
			if(!quiet)
				printf("slot2_status: ");
			printf("%d\n", (ykds_touch_level(st) & CONFIG2_VALID) == CONFIG2_VALID);
		}
		ykds_free(st);
	}
	if(vid || pid) {
		int vendor_id, product_id;
		if(!yk_get_key_vid_pid(yk, &vendor_id, &product_id)) {
			exit_code = 1;
			goto err;
		}
		if(vid) {
			if(!quiet)
				printf("vendor_id: ");
			printf("%x\n", vendor_id);
		}
		if(pid) {
			if(!quiet)
				printf("product_id: ");
			printf("%x\n", product_id);
		}
	}

	exit_code = 0;
	error = false;

err:
	if (error || exit_code != 0) {
		report_yk_error();
	}

	if (yk && !yk_close_key(yk)) {
		report_yk_error();
		exit_code = 2;
	}

	if (!yk_release()) {
		report_yk_error();
		exit_code = 2;
	}

	exit(exit_code);
}
コード例 #15
0
ファイル: ykparse.c プロジェクト: Yubico/yubico-c
int
main (int argc, char *argv[])
{
    uint8_t buf[128];
    uint8_t key[YUBIKEY_KEY_SIZE];
    char *aeskey, *token;
    yubikey_token_st tok;

    /* Parse command line parameters. */
    if (argc <= 2)
    {
        printf ("Usage: %s <aeskey> <token>\n", argv[0]);
        printf (" AESKEY:\tHex encoded AES-key.\n");
        printf (" TOKEN:\t\tModHex encoded token.\n");
        return EXIT_FAILURE;
    }

    aeskey = argv[1];
    token = argv[2];

    if (strlen (aeskey) != 32)
    {
        printf ("error: Hex encoded AES-key must be 32 characters.\n");
        return EXIT_FAILURE;
    }

    if (strlen (token) > 32)
    {
        printf ("warning: overlong token, ignoring prefix: %.*s\n",
                (int) strlen (token) - 32, token);
        token = token + (strlen (token) - 32);
    }

    if (strlen (token) != 32)
    {
        printf ("error: ModHex encoded token must be 32 characters.\n");
        return EXIT_FAILURE;
    }

    /* Debug. */
    printf ("Input:\n");
    printf ("  token: %s\n", token);

    yubikey_modhex_decode ((char *) key, token, YUBIKEY_KEY_SIZE);

    {
        size_t i;
        printf ("          ");
        for (i = 0; i < YUBIKEY_KEY_SIZE; i++)
            printf ("%02x ", key[i] & 0xFF);
        printf ("\n");
    }

    printf ("  aeskey: %s\n", aeskey);

    yubikey_hex_decode ((char *) key, aeskey, YUBIKEY_KEY_SIZE);

    {
        size_t i;
        printf ("          ");
        for (i = 0; i < YUBIKEY_KEY_SIZE; i++)
            printf ("%02x ", key[i] & 0xFF);
        printf ("\n");
    }

    /* Pack up dynamic password, decrypt it and verify checksum */
    yubikey_parse ((uint8_t *) token, key, &tok);

    printf ("Output:\n");
    {
        size_t i;
        printf ("          ");
        for (i = 0; i < YUBIKEY_BLOCK_SIZE; i++)
            printf ("%02x ", ((uint8_t *) & tok)[i] & 0xFF);
        printf ("\n");
    }

    printf ("\nStruct:\n");
    /* Debug */
    {
        size_t i;
        printf ("  uid: ");
        for (i = 0; i < YUBIKEY_UID_SIZE; i++)
            printf ("%02x ", tok.uid[i] & 0xFF);
        printf ("\n");
    }
    printf ("  counter: %d (0x%04x)\n", tok.ctr, tok.ctr);
    printf ("  timestamp (low): %d (0x%04x)\n", tok.tstpl, tok.tstpl);
    printf ("  timestamp (high): %d (0x%02x)\n", tok.tstph, tok.tstph);
    printf ("  session use: %d (0x%02x)\n", tok.use, tok.use);
    printf ("  random: %d (0x%02x)\n", tok.rnd, tok.rnd);
    printf ("  crc: %d (0x%04x)\n", tok.crc, tok.crc);

    printf ("\nDerived:\n");
    printf ("  cleaned counter: %d (0x%04x)\n",
            yubikey_counter (tok.ctr), yubikey_counter (tok.ctr));
    yubikey_modhex_encode ((char *) buf, (char *) tok.uid, YUBIKEY_UID_SIZE);
    printf ("  modhex uid: %s\n", buf);
    printf ("  triggered by caps lock: %s\n",
            yubikey_capslock (tok.ctr) ? "yes" : "no");
    printf ("  crc: %04X\n", yubikey_crc16 ((void *) &tok, YUBIKEY_KEY_SIZE));

    printf ("  crc check: ");
    if (yubikey_crc_ok_p ((uint8_t *) & tok))
    {
        printf ("ok\n");
        return EXIT_SUCCESS;
    }

    printf ("fail\n");
    return EXIT_FAILURE;
}
コード例 #16
0
static int yubikey_auth_core(myConf_t *myConf, REQUEST *request)
{
    int passLen = 0, session = 0, counter = 0, i = 0;
    MD5_CTX ctx;
    int result = 0;
    char *filename = "/usr/local/etc/raddb/yubico/users";

    //get password by removing the last 32 characters of the password
    if (strlen(request->password->vp_strvalue) <= 32)
    {
        DEBUG("rlm_yubikey: Password too short.");
        return RLM_MODULE_REJECT;
    }

    passLen = strlen(request->password->vp_strvalue) - 32;
    strncpy(myConf->pass, request->password->vp_strvalue, passLen);
    myConf->pass[passLen] = '\0';
    strncpy(myConf->token, request->password->vp_strvalue + passLen, 32);
    myConf->token[32] = '\0';

    //md5 stuff
    MD5Init(&ctx);
    DEBUG("rlm_yubikey: length: %d, string: %s", passLen, myConf->pass);
    MD5Update(&ctx, (unsigned char *)myConf->pass, passLen);
    MD5Final(&ctx);
    MD5toString(&ctx, myConf->md5ComputedString);
    myConf->md5ComputedString[32] = '\0';
    DEBUG("rlm_yubikey: MD5string of your pass: %s", myConf->md5ComputedString);
    DEBUG("rlm_yubikey: Username: %s", request->username->vp_strvalue);

    //read file
    result = config_read_file(&(myConf->config), filename);
    if (result != CONFIG_TRUE)
    {
        DEBUG("rlm_yubikey: Failed to parse configuration file: config_read_file (&config, filename);");
        DEBUG("config_error_text()= %s and config_error_line()=%d", config_error_text(&(myConf->config)), config_error_line(&(myConf->config)));
        return RLM_MODULE_FAIL;
    }

    //parse file
    myConf->config_setting = config_lookup(&(myConf->config), USERS_PATH);
    if (myConf->config_setting == NULL)
    {
        DEBUG("rlm_yubikey: Failed to parse configuration file: config_lookup failed to find the users node");
        return RLM_MODULE_FAIL;
    }

    //go through the list of users
    for (i = 0; i < config_setting_length(myConf->config_setting); i++)
    {
        DEBUG("Trying i: %d", i);
        config_setting_t *tmpSetting = NULL;
        tmpSetting = config_setting_get_elem(myConf->config_setting, i);
        if (tmpSetting == NULL)
        {
            DEBUG("rlm_yubikey: Failed to parse configuration file: config_setting_get_elem(config_setting,i);");
            return RLM_MODULE_FAIL;
        }

        if ((config_setting_get_string_elem(tmpSetting, 0) == NULL) ||
                (config_setting_get_string_elem(tmpSetting, 1) == NULL) ||
                (config_setting_get_string_elem(tmpSetting, 2) == NULL))
        {
            DEBUG("rlm_yubikey: Failed to parse configuration file while reading the username/password/aeskey triplet ");
            return RLM_MODULE_FAIL;
        }

        //check usernames are equal
        if (strcmp(request->username->vp_strvalue, config_setting_get_string_elem(tmpSetting, 0)) != 0)
        {
            //users do not match. No need to debug this
            //Go to next iteration
            continue;
        }

        //check passwords are equal
        if (strcmp(myConf->md5ComputedString, config_setting_get_string_elem(tmpSetting, 1)) != 0)
        {
            //passwords do not match. We debug
            DEBUG("rlm_yubikey: Password does not match for user %s", request->username->vp_strvalue);
            //Go to next iteration
            continue;
        }

        //check aes stuff - mostly copied from the ykdebug.c that comes with the low-level yubikey library
        uint8_t buf[128];
        const char *aeskey = config_setting_get_string_elem(tmpSetting, 2);
        char *token = myConf->token;
        uint8_t key[YUBIKEY_KEY_SIZE];
        yubikey_token_st tok;

        yubikey_modhex_decode((char*) key, token, YUBIKEY_KEY_SIZE);
        DEBUG("rlm_yubikey:  aeskey: %s", aeskey);

        yubikey_hex_decode((char*) key, aeskey, YUBIKEY_KEY_SIZE);

        /* Pack up dynamic password, decrypt it and verify checksum */
        yubikey_parse((uint8_t*) token, key, &tok);

        DEBUG("rlm_yubikey: Struct:");
        size_t i;
        char *tmp = (char*) malloc(1024);
        for (i = 0; i < YUBIKEY_UID_SIZE; i++)
        {
            sprintf(tmp + i, "%c ", tok.uid[i] & 0xFF);
        }
        tmp[YUBIKEY_UID_SIZE + i] = 0;
        DEBUG("rlm_yubikey:   uid:%s", tmp);
        free(tmp);

        DEBUG("rlm_yubikey:   counter: %d (0x%04x)", tok.ctr, tok.ctr);
        DEBUG("rlm_yubikey:   timestamp (low): %d (0x%04x)", tok.tstpl, tok.tstpl);
        DEBUG("rlm_yubikey:   timestamp (high): %d (0x%02x)", tok.tstph, tok.tstph);
        DEBUG("rlm_yubikey:   session use: %d (0x%02x)", tok.use, tok.use);
        DEBUG("rlm_yubikey:   random: %d (0x%02x)", tok.rnd, tok.rnd);
        DEBUG("rlm_yubikey:   crc: %d (0x%04x)", tok.crc, tok.crc);
        DEBUG("rlm_yubikey: Derived:");
        DEBUG("rlm_yubikey:   cleaned counter: %d (0x%04x)",yubikey_counter(tok.ctr), yubikey_counter(tok.ctr));

        yubikey_modhex_encode((char*) buf, (char*) tok.uid, YUBIKEY_UID_SIZE);

        DEBUG("rlm_yubikey:   modhex uid: %s", buf);
        DEBUG("rlm_yubikey:   triggered by caps lock: %s", yubikey_capslock(tok.ctr) ? "yes" : "no");
        DEBUG("rlm_yubikey:   crc: %04X", yubikey_crc16((void*) & tok, YUBIKEY_KEY_SIZE));
        DEBUG("rlm_yubikey:   crc check: ");
        if (yubikey_crc_ok_p((uint8_t*) & tok))
        {
            DEBUG("rlm_yubikey:   ok");

            char *tmppath = KEYS_PATH;
            char *path = (char*) malloc(strlen(tmppath) + 32 + 1);
            strcpy(path, tmppath);
            strcat(path, aeskey);


            myConf->config_setting = config_lookup(&(myConf->config), path);
            if (myConf->config_setting == NULL)
            {
                DEBUG("rlm_yubikey: Error parsing file: %s not found", path);
                return RLM_MODULE_FAIL;
            }

            //checking counter and session and update them if necessary
            counter = config_setting_get_int_elem(myConf->config_setting, 0);
            session = config_setting_get_int_elem(myConf->config_setting, 1);
            DEBUG("rlm_yubikey: Read counter: %d, session: %d", counter, session);

            if ((tok.ctr < counter)||((tok.ctr == counter) && (tok.use <= session)))
            {
                DEBUG("rlm_yubikey: someone tried to login with an old generated hash");
                return RLM_MODULE_REJECT;
            }

            //updating config file with counter and session
            config_setting_set_int_elem(myConf->config_setting, 0, tok.ctr);
            config_setting_set_int_elem(myConf->config_setting, 1, tok.use);


            DEBUG("rlm_yubikey: Written element: %ld", config_setting_get_int_elem(myConf->config_setting, 0));
            DEBUG("rlm_yubikey: Written element: %ld", config_setting_get_int_elem(myConf->config_setting, 1));
            if (CONFIG_FALSE == config_write_file(&(myConf->config), filename))
            {
                DEBUG("rlm_yubikey: Failed to write the file.");
                return RLM_MODULE_FAIL;
            }

            return RLM_MODULE_OK;
        }
        DEBUG("rlm_yubikey:   fail");
    }
    DEBUG("rlm_yubikey: Authenticating with password %s", request->password->vp_strvalue);
    return RLM_MODULE_REJECT;
}
コード例 #17
0
static int
yubikey_login(const char *username, const char *password)
{
	char fn[MAXPATHLEN];
	char hexkey[33], key[YUBIKEY_KEY_SIZE];
	char hexuid[13], uid[YUBIKEY_UID_SIZE];
	FILE *f;
	yubikey_token_st tok;
	u_int32_t last_ctr = 0, ctr;
	int r, i = 0, mapok = 0, crcok = 0;

	snprintf(fn, sizeof(fn), "%s/%s.uid", path, username);
	if ((f = fopen(fn, "r")) == NULL) {
		syslog(LOG_ERR, "user %s: fopen: %s: %m", username, fn);
		return (AUTH_FAILED);
	}
	if (fscanf(f, "%12s", hexuid) != 1) {
		syslog(LOG_ERR, "user %s: fscanf: %s: %m", username, fn);
		fclose(f);
		return (AUTH_FAILED);
	}
	fclose(f);

	snprintf(fn, sizeof(fn), "%s/%s.key", path, username);
	if ((f = fopen(fn, "r")) == NULL) {
		syslog(LOG_ERR, "user %s: fopen: %s: %m", username, fn);
		return (AUTH_FAILED);
	}
	if (fscanf(f, "%32s", hexkey) != 1) {
		syslog(LOG_ERR, "user %s: fscanf: %s: %m", username, fn);
		fclose(f);
		return (AUTH_FAILED);
	}
	fclose(f);
	if (strlen(hexkey) != 32) {
		syslog(LOG_ERR, "user %s: key len != 32", username);
		return (AUTH_FAILED);
	}

	snprintf(fn, sizeof(fn), "%s/%s.ctr", path, username);
	if ((f = fopen(fn, "r")) != NULL) {
		if (fscanf(f, "%u", &last_ctr) != 1)
			last_ctr = 0;
		fclose(f);
	}

	yubikey_hex_decode(uid, hexuid, YUBIKEY_UID_SIZE);
	yubikey_hex_decode(key, hexkey, YUBIKEY_KEY_SIZE);

	/* 
	 * Cycle through the key mapping table.
         * XXX brute force, unoptimized; a lookup table for valid mappings may
	 * be appropriate.
	 */
	while (1) {
		r = yubikey_parse((uint8_t *)password, (uint8_t *)key, &tok, i++);
		switch (r) {
		case EMSGSIZE:
			syslog(LOG_INFO, "user %s failed: password too short.",
			    username);
			return (AUTH_FAILED);
		case EINVAL: 	/* keyboard mapping invalid */
			continue;
		case 0:		/* found a valid keyboard mapping */
			mapok++;
			if (!yubikey_crc_ok_p((uint8_t *)&tok))
				continue;	/* try another one */
			crcok++;
			syslog(LOG_DEBUG, "user %s: crc %04x ok",
			    username, tok.crc);

			if (memcmp(tok.uid, uid, YUBIKEY_UID_SIZE)) {
				char h[13];

				yubikey_hex_encode(h, (const char *)tok.uid,
				    YUBIKEY_UID_SIZE);
				syslog(LOG_DEBUG, "user %s: uid %s != %s",
				    username, h, hexuid);
				continue;	/* try another one */
			}
			break; /* uid matches */
		case -1:
			syslog(LOG_INFO, "user %s: could not decode password "
			    "with any keymap (%d crc ok)",
			    username, crcok);
			return (AUTH_FAILED);
		default: 
			syslog(LOG_DEBUG, "user %s failed: %s",
			    username, strerror(r));
			return (AUTH_FAILED);
		}
		break; /* only reached through the bottom of case 0 */
	}

	syslog(LOG_INFO, "user %s uid %s: %d matching keymaps (%d checked), "
	    "%d crc ok", username, hexuid, mapok, i, crcok);

	ctr = ((u_int32_t)yubikey_counter(tok.ctr) << 8) | tok.use;
	if (ctr <= last_ctr) {
		syslog(LOG_INFO, "user %s: counter %u.%u <= %u.%u "
		    "(REPLAY ATTACK!)", username, ctr / 256, ctr % 256,
		    last_ctr / 256, last_ctr % 256);
		return (AUTH_FAILED);
	}
	syslog(LOG_INFO, "user %s: counter %u.%u > %u.%u",
	    username, ctr / 256, ctr % 256, last_ctr / 256, last_ctr % 256);
	umask(S_IRWXO);
	if ((f = fopen(fn, "w")) == NULL) {
		syslog(LOG_ERR, "user %s: fopen: %s: %m", username, fn);
		return (AUTH_FAILED);
	}
	fprintf(f, "%u", ctr);
	fclose(f);

	return (AUTH_OK);
}
コード例 #18
0
ファイル: util.c プロジェクト: mabels/yubico-pam
int
load_chalresp_state(FILE *f, CR_STATE *state, bool verbose)
{
  /*
   * Load the current challenge and expected response information from a file handle.
   *
   * Format is hex(challenge):hex(response):slot num
   */
  char challenge_hex[CR_CHALLENGE_SIZE * 2 + 1], response_hex[CR_RESPONSE_SIZE * 2 + 1];
  char salt_hex[CR_SALT_SIZE * 2 + 1];
  unsigned int iterations;
  int slot;
  int r;

  if (! f)
    goto out;

  /* XXX not ideal with hard coded lengths in this scan string.
   * 126 corresponds to twice the size of CR_CHALLENGE_SIZE,
   * 40 is twice the size of CR_RESPONSE_SIZE
   * (twice because we hex encode the challenge and response)
   */
  r = fscanf(f, "v2:%126[0-9a-z]:%40[0-9a-z]:%64[0-9a-z]:%d:%d", challenge_hex, response_hex, salt_hex, &iterations, &slot);
  if(r == 5) {
    if (! yubikey_hex_p(salt_hex)) {
      D(("Invalid salt hex input : %s", salt_hex));
      goto out;
    }

    if(verbose) {
      D(("Challenge: %s, hashed response: %s, salt: %s, iterations: %d, slot: %d",
            challenge_hex, response_hex, salt_hex, iterations, slot));
    }

    yubikey_hex_decode(state->salt, salt_hex, sizeof(state->salt));
    state->salt_len = strlen(salt_hex) / 2;
  } else {
    rewind(f);
    r = fscanf(f, "v1:%126[0-9a-z]:%40[0-9a-z]:%d", challenge_hex, response_hex, &slot);
    if (r != 3) {
      D(("Could not parse contents of chalresp_state file (%i)", r));
      goto out;
    }

    if (verbose) {
      D(("Challenge: %s, expected response: %s, slot: %d", challenge_hex, response_hex, slot));
    }

    iterations = CR_DEFAULT_ITERATIONS;
  }

  state->iterations = iterations;


  if (! yubikey_hex_p(challenge_hex)) {
    D(("Invalid challenge hex input : %s", challenge_hex));
    goto out;
  }

  if (! yubikey_hex_p(response_hex)) {
    D(("Invalid expected response hex input : %s", response_hex));
    goto out;
  }

  if (slot != 1 && slot != 2) {
    D(("Invalid slot input : %i", slot));
    goto out;
  }

  yubikey_hex_decode(state->challenge, challenge_hex, sizeof(state->challenge));
  state->challenge_len = strlen(challenge_hex) / 2;

  yubikey_hex_decode(state->response, response_hex, sizeof(state->response));
  state->response_len = strlen(response_hex) / 2;

  state->slot = slot;

  return 1;

 out:
  return 0;
}
コード例 #19
0
int main(int argc, char **argv)
{
	YK_KEY *yk = 0;
	bool error = true;
	int exit_code = 0;

	/* Options */
	bool serial_dec = false;
	bool serial_modhex = false;
	bool serial_hex = false;
	bool version = false;
	bool touch_level = false;
	bool pgm_seq = false;

	bool quiet = false;

	yk_errno = 0;

	if (! parse_args(argc, argv,
				&serial_dec, &serial_modhex, &serial_hex,
				&version, &touch_level, &pgm_seq, &quiet,
				&exit_code))
		exit(exit_code);

	if (!yk_init()) {
		exit_code = 1;
		goto err;
	}

	if (!(yk = yk_open_first_key())) {
		exit_code = 1;
		goto err;
	}

	if(serial_dec || serial_modhex || serial_hex) {
		unsigned int serial;
		int ret = yk_get_serial(yk, 1, 0, &serial);
		if(!ret) {
			exit_code = 1;
			goto err;
		}
		if(serial_dec) {
			if(!quiet)
				printf("serial: ");
			printf("%d\n", serial);
		}
		if(serial_hex) {
			if(!quiet)
				printf("serial_hex: ");
			printf("%x\n", serial);
		}
		if(serial_modhex) {
			char buf[64];
			char hex_serial[64];
			char modhex_serial[64];

			snprintf(buf, 64, "%x", serial);
			yubikey_hex_decode(hex_serial, buf, strlen(buf));
			yubikey_modhex_encode(modhex_serial, hex_serial, strlen(hex_serial));
			if(!quiet)
				printf("serial_modhex: ");
			printf("%s\n", modhex_serial);
		}
	}
	if(version || touch_level || pgm_seq) {
		YK_STATUS *st = ykds_alloc();
		if(!yk_get_status(yk, st)) {
			ykds_free(st);
			exit_code = 1;
			goto err;
		}

		if(version) {
			if(!quiet)
				printf("version: ");
			printf("%d.%d.%d\n", ykds_version_major(st), ykds_version_minor(st), ykds_version_build(st));
		}
		if(touch_level) {
			if(!quiet)
				printf("touch_level: ");
			printf("%d\n", ykds_touch_level(st));
		}
		if(pgm_seq) {
			if(!quiet)
				printf("programming_sequence: ");
			printf("%d\n", ykds_pgm_seq(st));
		}
		ykds_free(st);
	}

	exit_code = 0;
	error = false;

err:
	if (error || exit_code != 0) {
		report_yk_error();
	}

	if (yk && !yk_close_key(yk)) {
		report_yk_error();
		exit_code = 2;
	}

	if (!yk_release()) {
		report_yk_error();
		exit_code = 2;
	}

	exit(exit_code);
}