예제 #1
0
파일: cli.c 프로젝트: mhfan/stoken
static void unlock_token(struct securid_token *t, int get_pin, char **ret_pass)
{
	char devid[BUFLEN] = { 0 }, pass[BUFLEN] = { 0 }, pin[BUFLEN];
	int rc;

	if (securid_devid_required(t))
		request_devid(t, devid);

	if (securid_pass_required(t))
		request_pass("Enter password to decrypt token: ",
			     t, pass, devid);

	rc = securid_decrypt_seed(t, pass, devid);
	if (rc != ERR_NONE)
		die("error: can't decrypt token: %s\n", stoken_errstr[rc]);

	if (t->enc_pin_str)
		if (securid_decrypt_pin(t->enc_pin_str, pass, t->pin) !=
		    ERR_NONE)
			warn("warning: can't decrypt PIN\n");

	if (ret_pass && strlen(pass))
		*ret_pass = xstrdup(pass);

	/* always allow --pin to override .stokenrc */
	if (get_pin && securid_pin_required(t) &&
	    (!strlen(t->pin) || opt_pin)) {
		request_pin("Enter PIN:", pin);
		strncpy(t->pin, pin, MAX_PIN + 1);
	}
}
예제 #2
0
/*
  PIN helper is an external app that asks user for a PIN. It can 
  implement its own PIN  code generation policy and methods like
  PIN look up in some database, etc. 
  HCId expects following output from PIN helper:
	PIN:12345678	-	PIN code
	ERR		-	No PIN available
*/
static void call_pin_helper(int dev, bdaddr_t *sba, struct hci_conn_info *ci)
{
	pin_code_reply_cp pr;
	struct sigaction sa;
	char addr[18], str[512], *pin, name[249], tmp[497], *ptr;
	FILE *pipe;
	int i, ret, len;

	/* Run PIN helper in the separate process */
#ifdef __uClinux__
	switch (vfork()) {
#else
	switch (fork()) {
#endif
		case 0:
			break;
		case -1:
			syslog(LOG_ERR, "Can't fork PIN helper: %s (%d)",
							strerror(errno), errno);
		default:
			return;
	}

	if (access(hcid.pin_helper, R_OK | X_OK)) {
		syslog(LOG_ERR, "Can't exec PIN helper %s: %s (%d)",
					hcid.pin_helper, strerror(errno), errno);
		goto reject;
	}

	memset(name, 0, sizeof(name));
	read_device_name(sba, &ci->bdaddr, name);
	//hci_remote_name(dev, &ci->bdaddr, sizeof(name), name, 0);

	memset(tmp, 0, sizeof(tmp));
	ptr = tmp;

	for (i = 0; i < 248 && name[i]; i++)
		if (isprint(name[i])) {
			switch (name[i]) {
			case '"':
			case '`':
			case '$':
			case '|':
			case '>':
			case '<':
			case '&':
			case ';':
			case '\\':
				*ptr++ = '\\';
			}
			*ptr++ = name[i];
		} else {
			name[i] = '.';
			*ptr++ = '.';
		}

	ba2str(&ci->bdaddr, addr);
	snprintf(str, sizeof(str), "%s %s %s \"%s\"", hcid.pin_helper,
					ci->out ? "out" : "in", addr, tmp);

	setenv("PATH", "/bin:/usr/bin:/usr/local/bin", 1);

	memset(&sa, 0, sizeof(sa));
	sa.sa_flags = SA_NOCLDSTOP;
	sa.sa_handler = SIG_DFL;
	sigaction(SIGCHLD, &sa, NULL);

	pipe = popen(str, "r");
	if (!pipe) {
		syslog(LOG_ERR, "Can't exec PIN helper: %s (%d)",
							strerror(errno), errno);
		goto reject;
	}

	pin = fgets(str, sizeof(str), pipe);
	ret = pclose(pipe);

	if (!pin || strlen(pin) < 5)
		goto nopin;

	strtok(pin, "\n\r");

	if (strncmp("PIN:", pin, 4))
		goto nopin;

	pin += 4;
	len  = strlen(pin);

	memset(&pr, 0, sizeof(pr));
	bacpy(&pr.bdaddr, &ci->bdaddr);
	memcpy(pr.pin_code, pin, len);
	pr.pin_len = len;
	hci_send_cmd(dev, OGF_LINK_CTL, OCF_PIN_CODE_REPLY,
			PIN_CODE_REPLY_CP_SIZE, &pr);
#ifdef __uClinux__
	_exit(0);
#else
	exit(0);
#endif

nopin:
	if (!pin || strncmp("ERR", pin, 3))
		syslog(LOG_ERR, "PIN helper exited abnormally with code %d", ret);

reject:
	hci_send_cmd(dev, OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY, 6, &ci->bdaddr);
#ifdef __uClinux__
	_exit(0);
#else
	exit(0);
#endif
}

static void request_pin(int dev, bdaddr_t *sba, struct hci_conn_info *ci)
{
#ifdef ENABLE_DBUS
	if (hcid.dbus_pin_helper) {
		hcid_dbus_request_pin(dev, ci);
		return;
	}
#endif
	call_pin_helper(dev, sba, ci);
}

static void pin_code_request(int dev, bdaddr_t *sba, bdaddr_t *dba)
{
	pin_code_reply_cp pr;
	struct hci_conn_info_req *cr;
	struct hci_conn_info *ci;
	char sa[18], da[18], pin[17];
	int pinlen;

	memset(&pr, 0, sizeof(pr));
	bacpy(&pr.bdaddr, dba);

	ba2str(sba, sa); ba2str(dba, da);
	syslog(LOG_INFO, "pin_code_request (sba=%s, dba=%s)", sa, da);

	cr = malloc(sizeof(*cr) + sizeof(*ci));
	if (!cr)
		return;

	bacpy(&cr->bdaddr, dba);
	cr->type = ACL_LINK;
	if (ioctl(dev, HCIGETCONNINFO, (unsigned long) cr) < 0) {
		syslog(LOG_ERR, "Can't get conn info: %s (%d)",
							strerror(errno), errno);
		goto reject;
	}
	ci = cr->conn_info;

	memset(pin, 0, sizeof(pin));
	pinlen = read_pin_code(sba, dba, pin);

	if (pairing == HCID_PAIRING_ONCE) {
		struct link_key *key = get_link_key(sba, dba);
		if (key) {
			ba2str(dba, da);
			syslog(LOG_WARNING, "PIN code request for already paired device %s", da);
			goto reject;
		}
	} else if (pairing == HCID_PAIRING_NONE)
		goto reject;

	if (hcid.security == HCID_SEC_AUTO) {
		if (!ci->out) {
			/* Incomming connection */
			memcpy(pr.pin_code, hcid.pin_code, hcid.pin_len);
			pr.pin_len = hcid.pin_len;
			hci_send_cmd(dev, OGF_LINK_CTL, OCF_PIN_CODE_REPLY,
				PIN_CODE_REPLY_CP_SIZE, &pr);
		} else {
			/* Outgoing connection */
			if (pinlen > 0) {
				memcpy(pr.pin_code, pin, pinlen);
				pr.pin_len = pinlen;
				hci_send_cmd(dev, OGF_LINK_CTL, OCF_PIN_CODE_REPLY,
					PIN_CODE_REPLY_CP_SIZE, &pr);
			} else {
				/* Let PIN helper handle that */ 
				request_pin(dev, sba, ci);
			}
		}
	} else {
		/* Let PIN helper handle that */ 
		request_pin(dev, sba, ci);
	}
	free(cr);
	return;

reject:
	hci_send_cmd(dev, OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY, 6, dba);
	free(cr);
	return;
}