예제 #1
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;
}
int YubiKeyUtil::hexModhexEncode(char *result, size_t *resultLen,
                                 const unsigned char *str, size_t strLen,
                                 bool modhex)
{
    *resultLen = strLen * 2;
    if (modhex) {
        yubikey_modhex_encode((char *)result, (char *)str, strLen);
        return 1;
    } else {
        yubikey_hex_encode((char *)result, (char *)str, strLen);
        return 1;
    }

    return 0;
}
예제 #3
0
static void
modhex_test1 (void)
{
  char buf[1024];
  char buf2[1024];

  yubikey_modhex_encode (buf, "test", 4);
  printf ("modhex-encode(\"test\") = %s\n", buf);
  assert (strcmp (buf, "ifhgieif") == 0);
  printf ("Modhex-1.1 success\n");

  printf ("modhex-decode(\"%s\") = ", buf);
  yubikey_modhex_decode (buf2, buf, sizeof (buf2));
  printf ("%.*s\n", 4, buf2);
  assert (memcmp (buf2, "test", 4) == 0);
  printf ("Modhex-1.2 success\n");
}
int _ykp_json_export_cfg(const YKP_CONFIG *cfg, char *json, size_t len) {
	json_object *jobj = json_object_new_object();
	json_object *yprod_json = json_object_new_object();
	json_object *options_json = json_object_new_object();
	if(cfg) {
		YK_CONFIG ycfg = cfg->ykcore_config;

		int mode = MODE_OTP_YUBICO;
		struct map_st *p;
		json_object *target_config = NULL;
		json_object *prot_obj = NULL;
		int protection = ykp_get_acccode_type(cfg);

		if((ycfg.tktFlags & TKTFLAG_OATH_HOTP) == TKTFLAG_OATH_HOTP){
			if((ycfg.cfgFlags & CFGFLAG_CHAL_HMAC) == CFGFLAG_CHAL_HMAC) {
				mode = MODE_CHAL_HMAC;
			} else if((ycfg.cfgFlags & CFGFLAG_CHAL_YUBICO) == CFGFLAG_CHAL_YUBICO) {
				mode = MODE_CHAL_YUBICO;
			} else {
				mode = MODE_OATH_HOTP;
			}
		}
		else if((ycfg.cfgFlags & CFGFLAG_STATIC_TICKET) == CFGFLAG_STATIC_TICKET) {
			mode = MODE_STATIC_TICKET;
		}

		for(p = _modes_map; p->flag; p++) {
			if(p->flag == mode) {
				json_object *jmode = json_object_new_string(p->json_text);
				json_object_object_add(yprod_json, "mode", jmode);
				break;
			}
		}

		if(cfg->command == SLOT_CONFIG) {
			target_config = json_object_new_int(1);
		} else if(cfg->command == SLOT_CONFIG2) {
			target_config = json_object_new_int(2);
		}
		if(target_config) {
			json_object_object_add(yprod_json, "targetConfig", target_config);
		}

		if(protection == YKP_ACCCODE_NONE) {
			prot_obj = json_object_new_string("none");
		} else if(protection == YKP_ACCCODE_RANDOM) {
			prot_obj = json_object_new_string("random");
		} else if(protection == YKP_ACCCODE_SERIAL) {
			prot_obj = json_object_new_string("id");
		}
		if(prot_obj) {
			json_object_object_add(yprod_json, "protection", prot_obj);
		}

		json_object_object_add(jobj, "yubiProdConfig", yprod_json);
		json_object_object_add(yprod_json, "options", options_json);


		if(ycfg.fixedSize != 0 && mode != MODE_STATIC_TICKET) {
			json_object *jPrefix;
			char prefix[5] = {0};

			json_object *scope;
			if(mode == MODE_OTP_YUBICO &&
					ycfg.fixed[0] == 0x00 && ycfg.fixed[1] == 0x00) {
				scope = json_object_new_string("yubiCloud");
			} else {
				scope = json_object_new_string("privatePrefix");
			}
			json_object_object_add(yprod_json, "scope", scope);

			yubikey_modhex_encode(prefix, (const char*)ycfg.fixed, 2);
			if(mode == MODE_OATH_HOTP) {
				int flag = ycfg.cfgFlags & CFGFLAG_OATH_FIXED_MODHEX;
				json_object *fixed_modhex = json_object_new_boolean(
						flag == CFGFLAG_OATH_FIXED_MODHEX ? 1 : 0);
				json_object_object_add(options_json, "fixedModhex", fixed_modhex);

				if(flag == 0) {
					yubikey_hex_encode(prefix, (const char*)ycfg.fixed, 2);
				} else if(flag == CFGFLAG_OATH_FIXED_MODHEX1) {
					yubikey_hex_encode(prefix + 2, (const char*)ycfg.fixed + 1, 1);
				}
			}
			jPrefix = json_object_new_string(prefix);
			json_object_object_add(yprod_json, "prefix", jPrefix);
		} else if(mode != MODE_STATIC_TICKET) {
			json_object *scope = json_object_new_string("noPublicId");
			json_object_object_add(yprod_json, "scope", scope);
		}

		if(mode == MODE_OATH_HOTP) {
			json_object *oathDigits;
			json_object *randomSeed;
			if((ycfg.cfgFlags & CFGFLAG_OATH_HOTP8) == CFGFLAG_OATH_HOTP8) {
				oathDigits = json_object_new_int(8);
			} else {
				oathDigits = json_object_new_int(6);
			}
			json_object_object_add(options_json, "oathDigits", oathDigits);

			if((ycfg.uid[5] == 0x01 || ycfg.uid[5] == 0x00) && ycfg.uid[4] == 0x00) {
				json_object *fixedSeedvalue = json_object_new_int(ycfg.uid[5] << 4);
				json_object_object_add(options_json, "fixedSeedvalue", fixedSeedvalue);
				randomSeed = json_object_new_boolean(0);
			} else {
				randomSeed = json_object_new_boolean(1);
			}
			json_object_object_add(options_json, "randomSeed", randomSeed);
		}

		for(p = _ticket_flags_map; p->flag; p++) {
			if(!p->json_text) {
				continue;
			}
			if(p->mode && (mode & p->mode) == mode) {
				int set = (ycfg.tktFlags & p->flag) == p->flag;
				json_object *jsetting = json_object_new_boolean(set);
				json_object_object_add(options_json, p->json_text, jsetting);
			}
		}

		for(p = _config_flags_map; p->flag; p++) {
			if(!p->json_text) {
				continue;
			}
			if(p->mode && (mode & p->mode) == mode) {
				int set = (ycfg.cfgFlags & p->flag) == p->flag;
				json_object *jsetting = json_object_new_boolean(set);
				json_object_object_add(options_json, p->json_text, jsetting);
			}
		}

		for(p = _extended_flags_map; p->flag; p++) {
			if(!p->json_text) {
				continue;
			}
			if(p->mode && (mode & p->mode) == mode) {
				int set = (ycfg.extFlags & p->flag) == p->flag;
				json_object *jsetting = json_object_new_boolean(set);
				json_object_object_add(options_json, p->json_text, jsetting);
			}
		}
	}

#ifdef HAVE_JSON_OBJECT_TO_JSON_STRING_EXT
	strncpy(json, json_object_to_json_string_ext(jobj, JSON_C_TO_STRING_PRETTY), len);
#else
	strncpy(json, json_object_to_json_string(jobj), len);
#endif

	/* free the root object, will free all children */
	json_object_put(jobj);
	return strlen(json);
}
예제 #5
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);
}
예제 #6
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;
}
예제 #7
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);
}
예제 #8
0
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;
}
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;
}
예제 #10
0
int ykp_write_config(const YKP_CONFIG *cfg,
		     int (*writer)(const char *buf, size_t count,
				   void *userdata),
		     void *userdata)
{
	if (cfg) {
		char buffer[256];
		struct map_st *p;
		unsigned char t_flags;
		bool key_bits_in_uid = false;

		/* for OATH-HOTP and HMAC-SHA1 challenge response, there is four bytes
		 *  additional key data in the uid field
		 */
		key_bits_in_uid = (_get_supported_key_length(cfg) == 20);

		/* fixed: */
		writer(str_fixed, strlen(str_fixed), userdata);
		writer(str_key_value_separator,
		       strlen(str_key_value_separator),
		       userdata);
		/* XXX print OATH-HOTP fixed differently based on oath-fixed-modhex etc. */
		writer(str_modhex_prefix,
		       strlen(str_key_value_separator),
		       userdata);
		yubikey_modhex_encode(buffer, (char *)cfg->ykcore_config.fixed, cfg->ykcore_config.fixedSize);
		writer(buffer, strlen(buffer), userdata);
		writer("\n", 1, userdata);

		/* uid: */
		writer(str_uid, strlen(str_uid), userdata);
		writer(str_key_value_separator,
		       strlen(str_key_value_separator),
		       userdata);
		if (key_bits_in_uid) {
			writer("n/a", 3, userdata);
		} else {
			writer(str_hex_prefix,
			       strlen(str_key_value_separator),
			       userdata);
			yubikey_hex_encode(buffer, (char *)cfg->ykcore_config.uid, UID_SIZE);
			writer(buffer, strlen(buffer), userdata);
		}
		writer("\n", 1, userdata);

		/* key: */
		writer(str_key, strlen(str_key), userdata);
		writer(str_key_value_separator,
		       strlen(str_key_value_separator),
		       userdata);
		writer(str_hex_prefix,
		       strlen(str_key_value_separator),
		       userdata);
		yubikey_hex_encode(buffer, (char *)cfg->ykcore_config.key, KEY_SIZE);
		if (key_bits_in_uid) {
			yubikey_hex_encode(buffer + KEY_SIZE * 2, (char *)cfg->ykcore_config.uid, 4);
		}
		writer(buffer, strlen(buffer), userdata);
		writer("\n", 1, userdata);

		/* acc_code: */
		writer(str_acc_code, strlen(str_acc_code), userdata);
		writer(str_key_value_separator,
		       strlen(str_key_value_separator),
		       userdata);
		writer(str_hex_prefix,
		       strlen(str_key_value_separator),
		       userdata);
		yubikey_hex_encode(buffer, (char *)cfg->ykcore_config.accCode, ACC_CODE_SIZE);
		writer(buffer, strlen(buffer), userdata);
		writer("\n", 1, userdata);

		/* ticket_flags: */
		buffer[0] = '\0';
		for (p = ticket_flags_map; p->flag; p++) {
			if ((cfg->ykcore_config.tktFlags & p->flag) == p->flag
			    && p->vcheck(cfg)) {
				if (*buffer) {
					strcat(buffer, str_flags_separator);
					strcat(buffer, p->flag_text);
				} else {
					strcpy(buffer, p->flag_text);
				}
			}
		}
		writer(str_ticket_flags, strlen(str_ticket_flags), userdata);
		writer(str_key_value_separator,
		       strlen(str_key_value_separator),
		       userdata);
		writer(buffer, strlen(buffer), userdata);
		writer("\n", 1, userdata);

		/* config_flags: */
		buffer[0] = '\0';
		t_flags = cfg->ykcore_config.cfgFlags;
		for (p = config_flags_map; p->flag; p++) {
			if ((t_flags & p->flag) == p->flag
			    && p->vcheck(cfg)
			    && (cfg->ykcore_config.tktFlags & p->tkt_context) == p->tkt_context) {
				if (*buffer) {
					strcat(buffer, str_flags_separator);
					strcat(buffer, p->flag_text);
				} else {
					strcpy(buffer, p->flag_text);
				}
				/* make sure we don't show more than one cfgFlag per value -
				   some cfgflags share value in different contexts
				*/
				t_flags -= p->flag;
			}
		}
		writer(str_config_flags, strlen(str_config_flags), userdata);
		writer(str_key_value_separator,
		       strlen(str_key_value_separator),
		       userdata);
		writer(buffer, strlen(buffer), userdata);
		writer("\n", 1, userdata);

		/* extended_flags: */
		buffer[0] = '\0';
		for (p = extended_flags_map; p->flag; p++) {
			if ((cfg->ykcore_config.extFlags & p->flag) == p->flag
			    && p->vcheck(cfg)) {
				if (*buffer) {
					strcat(buffer, str_flags_separator);
					strcat(buffer, p->flag_text);
				} else {
					strcpy(buffer, p->flag_text);
				}
			}
		}
		writer(str_extended_flags, strlen(str_extended_flags), userdata);
		writer(str_key_value_separator,
		       strlen(str_key_value_separator),
		       userdata);
		writer(buffer, strlen(buffer), userdata);
		writer("\n", 1, userdata);

		return 1;
	}
	return 0;
}
예제 #11
0
static int _ykp_legacy_export_config(const YKP_CONFIG *cfg, char *buf, size_t len) {
	if (cfg) {
		char buffer[256];
		struct map_st *p;
		unsigned char t_flags;
		bool key_bits_in_uid = false;
		YK_CONFIG ycfg = cfg->ykcore_config;
		int mode = MODE_OTP_YUBICO;

		int pos = 0;

		if((ycfg.tktFlags & TKTFLAG_OATH_HOTP) == TKTFLAG_OATH_HOTP){
			if((ycfg.cfgFlags & CFGFLAG_CHAL_HMAC) == CFGFLAG_CHAL_HMAC) {
				mode = MODE_CHAL_HMAC;
			} else if((ycfg.cfgFlags & CFGFLAG_CHAL_YUBICO) == CFGFLAG_CHAL_YUBICO) {
				mode = MODE_CHAL_YUBICO;
			} else {
				mode = MODE_OATH_HOTP;
			}
		}
		else if((ycfg.cfgFlags & CFGFLAG_STATIC_TICKET) == CFGFLAG_STATIC_TICKET) {
			mode = MODE_STATIC_TICKET;
		}

		/* for OATH-HOTP and HMAC-SHA1 challenge response, there is four bytes
		 *  additional key data in the uid field
		 */
		key_bits_in_uid = (_get_supported_key_length(cfg) == 20);

		/* fixed: or OATH id: */
		if ((ycfg.tktFlags & TKTFLAG_OATH_HOTP) == TKTFLAG_OATH_HOTP &&
		    ycfg.fixedSize) {
			/* First byte (vendor id) */
			if ((ycfg.cfgFlags & CFGFLAG_OATH_FIXED_MODHEX1) == CFGFLAG_OATH_FIXED_MODHEX1 ||
			    (ycfg.cfgFlags & CFGFLAG_OATH_FIXED_MODHEX2) == CFGFLAG_OATH_FIXED_MODHEX2 ||
			    (ycfg.cfgFlags & CFGFLAG_OATH_FIXED_MODHEX) == CFGFLAG_OATH_FIXED_MODHEX) {
				yubikey_modhex_encode(buffer, (const char *)ycfg.fixed, 1);
			} else {
				yubikey_hex_encode(buffer, (const char *)ycfg.fixed, 1);
			}
			/* Second byte (token type) */
			if ((ycfg.cfgFlags & CFGFLAG_OATH_FIXED_MODHEX2) == CFGFLAG_OATH_FIXED_MODHEX2 ||
			    (ycfg.cfgFlags & CFGFLAG_OATH_FIXED_MODHEX) == CFGFLAG_OATH_FIXED_MODHEX) {
				yubikey_modhex_encode(buffer + 2, (const char *)ycfg.fixed + 1, 1);
			} else {
				yubikey_hex_encode(buffer + 2, (const char *)ycfg.fixed + 1, 1);
			}
			/* bytes 3-12 - MUI */
			if ((ycfg.cfgFlags & CFGFLAG_OATH_FIXED_MODHEX) == CFGFLAG_OATH_FIXED_MODHEX) {
				yubikey_modhex_encode(buffer + 4, (const char *)ycfg.fixed + 2, 8);
			} else {
				yubikey_hex_encode(buffer + 4, (const char *)ycfg.fixed + 2, 8);
			}
			buffer[12] = 0;
			pos += snprintf(buf, len - (size_t)pos, "%s%s%s\n", str_oath_id, str_key_value_separator, buffer);
		} else {
			yubikey_modhex_encode(buffer, (const char *)ycfg.fixed, ycfg.fixedSize);
			pos += snprintf(buf, len - (size_t)pos, "%s%s%s%s\n", str_fixed, str_key_value_separator, str_modhex_prefix, buffer);
		}

		/* uid: */
		if (key_bits_in_uid) {
			strncpy(buffer, "n/a", 3);
		} else {
			yubikey_hex_encode(buffer, (const char *)ycfg.uid, UID_SIZE);
		}
		pos += snprintf(buf + pos, len - (size_t)pos, "%s%s%s\n", str_uid, str_key_value_separator, buffer);

		/* key: */
		yubikey_hex_encode(buffer, (const char *)ycfg.key, KEY_SIZE);
		if (key_bits_in_uid) {
			yubikey_hex_encode(buffer + KEY_SIZE * 2, (const char *)ycfg.uid, 4);
		}
		pos += snprintf(buf + pos, len - (size_t)pos, "%s%s%s%s\n", str_key, str_key_value_separator, str_hex_prefix, buffer);

		/* acc_code: */
		yubikey_hex_encode(buffer, (const char*)ycfg.accCode, ACC_CODE_SIZE);
		pos += snprintf(buf + pos, len - (size_t)pos, "%s%s%s%s\n", str_acc_code, str_key_value_separator, str_hex_prefix, buffer);

		/* OATH IMF: */
		if ((ycfg.tktFlags & TKTFLAG_OATH_HOTP) == TKTFLAG_OATH_HOTP &&
		    capability_has_oath_imf(cfg)) {
			pos += snprintf(buf + pos, len - (size_t)pos, "%s%s%s%lx\n", str_oath_imf, str_key_value_separator, str_hex_prefix, ykp_get_oath_imf(cfg));
		}

		/* ticket_flags: */
		buffer[0] = '\0';
		for (p = _ticket_flags_map; p->flag; p++) {
			if ((ycfg.tktFlags & p->flag) == p->flag
			    && p->capability(cfg)
			    && (mode & p->mode) == mode) {
				if (*buffer) {
					strcat(buffer, str_flags_separator);
					strcat(buffer, p->flag_text);
				} else {
					strcpy(buffer, p->flag_text);
				}
			}
		}
		pos += snprintf(buf + pos, len - (size_t)pos, "%s%s%s\n", str_ticket_flags, str_key_value_separator, buffer);

		/* config_flags: */
		buffer[0] = '\0';
		t_flags = ycfg.cfgFlags;
		for (p = _config_flags_map; p->flag; p++) {
			if ((t_flags & p->flag) == p->flag
			    && p->capability(cfg)
			    && (mode & p->mode) == mode) {
				if (*buffer) {
					strcat(buffer, str_flags_separator);
					strcat(buffer, p->flag_text);
				} else {
					strcpy(buffer, p->flag_text);
				}
				/* make sure we don't show more than one cfgFlag per value -
				   some cfgflags share value in different contexts
				*/
				t_flags -= p->flag;
			}
		}
		pos += snprintf(buf + pos, len - (size_t)pos, "%s%s%s\n", str_config_flags, str_key_value_separator, buffer);

		/* extended_flags: */
		buffer[0] = '\0';
		for (p = _extended_flags_map; p->flag; p++) {
			if ((ycfg.extFlags & p->flag) == p->flag
			    && p->capability(cfg)
			    && (mode & p->mode) == mode) {
				if (*buffer) {
					strcat(buffer, str_flags_separator);
					strcat(buffer, p->flag_text);
				} else {
					strcpy(buffer, p->flag_text);
				}
			}
		}
		pos += snprintf(buf + pos, len - (size_t)pos, "%s%s%s\n", str_extended_flags, str_key_value_separator, buffer);

		return pos;
	}
	return 0;
}