aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorWaldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>2011-06-01 11:28:48 -0400
committerGustavo F. Padovan <padovan@profusion.mobi>2011-06-08 15:58:19 -0400
commit96d97a673d42408c0f960cc54d44be7629343bce (patch)
tree3f4f236d0443705ed0e7180e4d188ca9300d96d4 /net
parent24718ca5eeb6d36a4a78deb34a2d50e4017bbd4a (diff)
Bluetooth: Verify a pin code in pin_code_reply
As we cannot relay on a userspace mgmt api implementation we should verify if pin_code_reply in fact contains the secure pin code. If userspace replied with unsecure pincode when secure was required we will send pin_code_neg_reply to the controller. Signed-off-by: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/mgmt.c53
1 files changed, 41 insertions, 12 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 54154235b4a7..fcccf10f909a 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1108,11 +1108,32 @@ unlock:
1108 return err; 1108 return err;
1109} 1109}
1110 1110
1111static int send_pin_code_neg_reply(struct sock *sk, u16 index,
1112 struct hci_dev *hdev, struct mgmt_cp_pin_code_neg_reply *cp)
1113{
1114 struct pending_cmd *cmd;
1115 int err;
1116
1117 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, index, cp,
1118 sizeof(*cp));
1119 if (!cmd)
1120 return -ENOMEM;
1121
1122 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(cp->bdaddr),
1123 &cp->bdaddr);
1124 if (err < 0)
1125 mgmt_pending_remove(cmd);
1126
1127 return err;
1128}
1129
1111static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data, 1130static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
1112 u16 len) 1131 u16 len)
1113{ 1132{
1114 struct hci_dev *hdev; 1133 struct hci_dev *hdev;
1134 struct hci_conn *conn;
1115 struct mgmt_cp_pin_code_reply *cp; 1135 struct mgmt_cp_pin_code_reply *cp;
1136 struct mgmt_cp_pin_code_neg_reply ncp;
1116 struct hci_cp_pin_code_reply reply; 1137 struct hci_cp_pin_code_reply reply;
1117 struct pending_cmd *cmd; 1138 struct pending_cmd *cmd;
1118 int err; 1139 int err;
@@ -1135,6 +1156,25 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
1135 goto failed; 1156 goto failed;
1136 } 1157 }
1137 1158
1159 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1160 if (!conn) {
1161 err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENOTCONN);
1162 goto failed;
1163 }
1164
1165 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
1166 bacpy(&ncp.bdaddr, &cp->bdaddr);
1167
1168 BT_ERR("PIN code is not 16 bytes long");
1169
1170 err = send_pin_code_neg_reply(sk, index, hdev, &ncp);
1171 if (err >= 0)
1172 err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
1173 EINVAL);
1174
1175 goto failed;
1176 }
1177
1138 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, index, data, len); 1178 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, index, data, len);
1139 if (!cmd) { 1179 if (!cmd) {
1140 err = -ENOMEM; 1180 err = -ENOMEM;
@@ -1161,7 +1201,6 @@ static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data,
1161{ 1201{
1162 struct hci_dev *hdev; 1202 struct hci_dev *hdev;
1163 struct mgmt_cp_pin_code_neg_reply *cp; 1203 struct mgmt_cp_pin_code_neg_reply *cp;
1164 struct pending_cmd *cmd;
1165 int err; 1204 int err;
1166 1205
1167 BT_DBG(""); 1206 BT_DBG("");
@@ -1185,17 +1224,7 @@ static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data,
1185 goto failed; 1224 goto failed;
1186 } 1225 }
1187 1226
1188 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, index, 1227 err = send_pin_code_neg_reply(sk, index, hdev, cp);
1189 data, len);
1190 if (!cmd) {
1191 err = -ENOMEM;
1192 goto failed;
1193 }
1194
1195 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(cp->bdaddr),
1196 &cp->bdaddr);
1197 if (err < 0)
1198 mgmt_pending_remove(cmd);
1199 1228
1200failed: 1229failed:
1201 hci_dev_unlock(hdev); 1230 hci_dev_unlock(hdev);