Exemple #1
0
int btd_event_request_pin(bdaddr_t *sba, bdaddr_t *dba)
{
	struct btd_adapter *adapter;
	struct btd_device *device;
	char pin[17];
	int pinlen;

	if (!get_adapter_and_device(sba, dba, &adapter, &device, TRUE))
		return -ENODEV;

	/* Check if the adapter is not pairable and if there isn't a bonding in
	 * progress */
	if (!adapter_is_pairable(adapter) && !device_is_bonding(device, NULL))
		return -EPERM;

	memset(pin, 0, sizeof(pin));
	pinlen = read_pin_code(sba, dba, pin);
	if (pinlen > 0) {
		btd_adapter_pincode_reply(adapter, dba, pin);
		return 0;
	}

	return device_request_authentication(device, AUTH_TYPE_PINCODE, 0,
								pincode_cb);
}
Exemple #2
0
int btd_event_request_pin(bdaddr_t *sba, bdaddr_t *dba)
{
	struct btd_adapter *adapter;
	struct btd_device *device;
	char pin[17];
	int pinlen;

	if (!get_adapter_and_device(sba, dba, &adapter, &device, TRUE))
		return -ENODEV;

	memset(pin, 0, sizeof(pin));
	pinlen = read_pin_code(sba, dba, pin);
	if (pinlen > 0) {
		btd_adapter_pincode_reply(adapter, dba, pin, pinlen);
		return 0;
	}

	return device_request_authentication(device, AUTH_TYPE_PINCODE, 0,
								pincode_cb);
}
Exemple #3
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;
}