mukesh agrawal | 4d0401c | 2012-01-06 16:05:31 -0800 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium OS Authors. All rights reserved. |
mukesh agrawal | 6e27777 | 2011-09-29 15:04:23 -0700 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "shill/wpa_supplicant.h" |
| 6 | |
Paul Stewart | 0654ece | 2013-03-26 15:21:26 -0700 | [diff] [blame] | 7 | #include <map> |
| 8 | #include <string> |
| 9 | #include <vector> |
| 10 | |
| 11 | #include <base/file_path.h> |
| 12 | |
| 13 | #include "shill/certificate_file.h" |
| 14 | #include "shill/eap_credentials.h" |
| 15 | #include "shill/nss.h" |
| 16 | |
| 17 | using base::FilePath; |
| 18 | using std::map; |
| 19 | using std::string; |
| 20 | using std::vector; |
| 21 | |
mukesh agrawal | 6e27777 | 2011-09-29 15:04:23 -0700 | [diff] [blame] | 22 | namespace shill { |
| 23 | |
Paul Stewart | 0654ece | 2013-03-26 15:21:26 -0700 | [diff] [blame] | 24 | // static |
| 25 | const char WPASupplicant::kBSSPropertyBSSID[] = "BSSID"; |
| 26 | const char WPASupplicant::kBSSPropertyFrequency[] = "Frequency"; |
| 27 | const char WPASupplicant::kBSSPropertyIEs[] = "IEs"; |
| 28 | const char WPASupplicant::kBSSPropertyMode[] = "Mode"; |
| 29 | const char WPASupplicant::kBSSPropertyRates[] = "Rates"; |
| 30 | const char WPASupplicant::kBSSPropertySSID[] = "SSID"; |
| 31 | const char WPASupplicant::kBSSPropertySignal[] = "Signal"; |
Gaurav Shah | 10109f2 | 2011-11-11 20:16:22 -0800 | [diff] [blame] | 32 | // TODO(gauravsh): Make this path be a configurable option. crosbug.com/25661 |
| 33 | // Location of the system root CA certificates. |
Paul Stewart | 0654ece | 2013-03-26 15:21:26 -0700 | [diff] [blame] | 34 | const char WPASupplicant::kCaPath[] = "/etc/ssl/certs"; |
| 35 | const char WPASupplicant::kCurrentBSSNull[] = "/"; |
| 36 | const char WPASupplicant::kDBusAddr[] = "fi.w1.wpa_supplicant1"; |
| 37 | const char WPASupplicant::kDBusPath[] = "/fi/w1/wpa_supplicant1"; |
| 38 | const char WPASupplicant::kDebugLevelDebug[] = "debug"; |
| 39 | const char WPASupplicant::kDebugLevelError[] = "error"; |
| 40 | const char WPASupplicant::kDebugLevelExcessive[] = "excessive"; |
| 41 | const char WPASupplicant::kDebugLevelInfo[] = "info"; |
| 42 | const char WPASupplicant::kDebugLevelMsgDump[] = "msgdump"; |
| 43 | const char WPASupplicant::kDebugLevelWarning[] = "warning"; |
| 44 | const char WPASupplicant::kDriverNL80211[] = "nl80211"; |
Paul Stewart | 196f50f | 2013-03-27 18:02:11 -0700 | [diff] [blame] | 45 | const char WPASupplicant::kDriverWired[] = "wired"; |
Paul Stewart | 0654ece | 2013-03-26 15:21:26 -0700 | [diff] [blame] | 46 | const char WPASupplicant::kEAPParameterAlertUnknownCA[] = "unknown CA"; |
| 47 | const char WPASupplicant::kEAPParameterFailure[] = "failure"; |
| 48 | const char WPASupplicant::kEAPParameterSuccess[] = "success"; |
| 49 | const char WPASupplicant::kEAPStatusAcceptProposedMethod[] = |
| 50 | "accept proposed method"; |
| 51 | const char WPASupplicant::kEAPStatusCompletion[] = "completion"; |
| 52 | const char WPASupplicant::kEAPStatusLocalTLSAlert[] = "local TLS alert"; |
| 53 | const char WPASupplicant::kEAPStatusParameterNeeded[] = "eap parameter needed"; |
| 54 | const char WPASupplicant::kEAPStatusRemoteCertificateVerification[] = |
Paul Stewart | db0f917 | 2012-11-30 16:48:09 -0800 | [diff] [blame] | 55 | "remote certificate verification"; |
Paul Stewart | 0654ece | 2013-03-26 15:21:26 -0700 | [diff] [blame] | 56 | const char WPASupplicant::kEAPStatusRemoteTLSAlert[] = "remote TLS alert"; |
| 57 | const char WPASupplicant::kEAPStatusStarted[] = "started"; |
| 58 | const char WPASupplicant::kEnginePKCS11[] = "pkcs11"; |
| 59 | const char WPASupplicant::kErrorNetworkUnknown[] |
| 60 | = "fi.w1.wpa_supplicant1.NetworkUnknown"; |
| 61 | const char WPASupplicant::kErrorInterfaceExists[] |
| 62 | = "fi.w1.wpa_supplicant1.InterfaceExists"; |
| 63 | const char WPASupplicant::kInterfacePropertyConfigFile[] = "ConfigFile"; |
| 64 | const char WPASupplicant::kInterfacePropertyCurrentBSS[] = "CurrentBSS"; |
| 65 | const char WPASupplicant::kInterfacePropertyDepth[] = "depth"; |
| 66 | const char WPASupplicant::kInterfacePropertyDriver[] = "Driver"; |
| 67 | const char WPASupplicant::kInterfacePropertyName[] = "Ifname"; |
| 68 | const char WPASupplicant::kInterfacePropertyState[] = "State"; |
| 69 | const char WPASupplicant::kInterfacePropertySubject[] = "subject"; |
| 70 | const char WPASupplicant::kInterfaceState4WayHandshake[] = "4way_handshake"; |
| 71 | const char WPASupplicant::kInterfaceStateAssociated[] = "associated"; |
| 72 | const char WPASupplicant::kInterfaceStateAssociating[] = "associating"; |
| 73 | const char WPASupplicant::kInterfaceStateAuthenticating[] = "authenticating"; |
| 74 | const char WPASupplicant::kInterfaceStateCompleted[] = "completed"; |
| 75 | const char WPASupplicant::kInterfaceStateDisconnected[] = "disconnected"; |
| 76 | const char WPASupplicant::kInterfaceStateGroupHandshake[] = "group_handshake"; |
| 77 | const char WPASupplicant::kInterfaceStateInactive[] = "inactive"; |
| 78 | const char WPASupplicant::kInterfaceStateScanning[] = "scanning"; |
| 79 | const char WPASupplicant::kKeyManagementMethodSuffixEAP[] = "-eap"; |
| 80 | const char WPASupplicant::kKeyManagementMethodSuffixPSK[] = "-psk"; |
| 81 | const char WPASupplicant::kKeyModeNone[] = "NONE"; |
| 82 | const char WPASupplicant::kNetworkBgscanMethodLearn[] = "learn"; |
Christopher Wiley | a998df2 | 2012-07-11 15:14:55 -0700 | [diff] [blame] | 83 | // None is not a real method name, but we interpret 'none' as a request that |
| 84 | // no background scan parameter should be supplied to wpa_supplicant. |
Paul Stewart | 0654ece | 2013-03-26 15:21:26 -0700 | [diff] [blame] | 85 | const char WPASupplicant::kNetworkBgscanMethodNone[] = "none"; |
| 86 | const char WPASupplicant::kNetworkBgscanMethodSimple[] = "simple"; |
| 87 | const char WPASupplicant::kNetworkModeInfrastructure[] = "infrastructure"; |
| 88 | const char WPASupplicant::kNetworkModeAdHoc[] = "ad-hoc"; |
| 89 | const char WPASupplicant::kNetworkModeAccessPoint[] = "ap"; |
| 90 | const char WPASupplicant::kNetworkPropertyBgscan[] = "bgscan"; |
| 91 | const char WPASupplicant::kNetworkPropertyCaPath[] = "ca_path"; |
| 92 | const char WPASupplicant::kNetworkPropertyEapIdentity[] = "identity"; |
| 93 | const char WPASupplicant::kNetworkPropertyEapKeyManagement[] = "key_mgmt"; |
| 94 | const char WPASupplicant::kNetworkPropertyEapEap[] = "eap"; |
| 95 | const char WPASupplicant::kNetworkPropertyEapInnerEap[] = "phase2"; |
| 96 | const char WPASupplicant::kNetworkPropertyEapAnonymousIdentity[] |
| 97 | = "anonymous_identity"; |
| 98 | const char WPASupplicant::kNetworkPropertyEapClientCert[] = "client_cert"; |
| 99 | const char WPASupplicant::kNetworkPropertyEapPrivateKey[] = "private_key"; |
| 100 | const char WPASupplicant::kNetworkPropertyEapPrivateKeyPassword[] = |
| 101 | "private_key_passwd"; |
| 102 | const char WPASupplicant::kNetworkPropertyEapCaCert[] = "ca_cert"; |
| 103 | const char WPASupplicant::kNetworkPropertyEapCaPassword[] = "password"; |
| 104 | const char WPASupplicant::kNetworkPropertyEapCertId[] = "cert_id"; |
| 105 | const char WPASupplicant::kNetworkPropertyEapKeyId[] = "key_id"; |
| 106 | const char WPASupplicant::kNetworkPropertyEapCaCertId[] = "ca_cert_id"; |
| 107 | const char WPASupplicant::kNetworkPropertyEapPin[] = "pin"; |
| 108 | const char WPASupplicant::kNetworkPropertyEapSubjectMatch[] = "subject_match"; |
| 109 | const char WPASupplicant::kNetworkPropertyEngine[] = "engine"; |
| 110 | const char WPASupplicant::kNetworkPropertyEngineId[] = "engine_id"; |
| 111 | const char WPASupplicant::kNetworkPropertyFrequency[] = "frequency"; |
| 112 | const char WPASupplicant::kNetworkPropertyIeee80211w[] = "ieee80211w"; |
| 113 | const char WPASupplicant::kNetworkPropertyMode[] = "mode"; |
| 114 | const char WPASupplicant::kNetworkPropertyScanSSID[] = "scan_ssid"; |
| 115 | const char WPASupplicant::kNetworkPropertySSID[] = "ssid"; |
| 116 | const char WPASupplicant::kPropertyAuthAlg[] = "auth_alg"; |
| 117 | const char WPASupplicant::kPropertyPreSharedKey[] = "psk"; |
| 118 | const char WPASupplicant::kPropertyPrivacy[] = "Privacy"; |
| 119 | const char WPASupplicant::kPropertyRSN[] = "RSN"; |
| 120 | const char WPASupplicant::kPropertyScanSSIDs[] = "SSIDs"; |
| 121 | const char WPASupplicant::kPropertyScanType[] = "Type"; |
| 122 | const char WPASupplicant::kPropertySecurityProtocol[] = "proto"; |
| 123 | const char WPASupplicant::kPropertyWEPKey[] = "wep_key"; |
| 124 | const char WPASupplicant::kPropertyWEPTxKeyIndex[] = "wep_tx_keyidx"; |
| 125 | const char WPASupplicant::kPropertyWPA[] = "WPA"; |
| 126 | const char WPASupplicant::kScanTypeActive[] = "active"; |
| 127 | const char WPASupplicant::kSecurityAuthAlg[] = "OPEN SHARED"; |
| 128 | const char WPASupplicant::kSecurityMethodPropertyKeyManagement[] = "KeyMgmt"; |
| 129 | const char WPASupplicant::kSecurityModeRSN[] = "RSN"; |
| 130 | const char WPASupplicant::kSecurityModeWPA[] = "WPA"; |
mukesh agrawal | 6e27777 | 2011-09-29 15:04:23 -0700 | [diff] [blame] | 131 | |
Paul Stewart | 0654ece | 2013-03-26 15:21:26 -0700 | [diff] [blame] | 132 | const uint32_t WPASupplicant::kDefaultEngine = 1; |
| 133 | const uint32_t WPASupplicant::kNetworkIeee80211wDisabled = 0; |
| 134 | const uint32_t WPASupplicant::kNetworkIeee80211wEnabled = 1; |
| 135 | const uint32_t WPASupplicant::kNetworkIeee80211wRequired = 2; |
| 136 | const uint32_t WPASupplicant::kNetworkModeInfrastructureInt = 0; |
| 137 | const uint32_t WPASupplicant::kNetworkModeAdHocInt = 1; |
| 138 | const uint32_t WPASupplicant::kNetworkModeAccessPointInt = 2; |
| 139 | const uint32_t WPASupplicant::kScanMaxSSIDsPerScan = 4; |
| 140 | |
Paul Stewart | 196f50f | 2013-03-27 18:02:11 -0700 | [diff] [blame] | 141 | const char WPASupplicant::kSupplicantConfPath[] = |
| 142 | SHIMDIR "/wpa_supplicant.conf"; |
| 143 | |
Paul Stewart | 0654ece | 2013-03-26 15:21:26 -0700 | [diff] [blame] | 144 | // static |
| 145 | void WPASupplicant::Populate8021xProperties( |
| 146 | const EapCredentials &eap, CertificateFile *certificate_file, |
| 147 | NSS *nss, const vector<char> nss_identifier, |
| 148 | map<string, DBus::Variant> *params) { |
| 149 | string ca_cert = eap.ca_cert; |
| 150 | if (!eap.ca_cert_pem.empty()) { |
| 151 | FilePath certfile = |
| 152 | certificate_file->CreateDERFromString(eap.ca_cert_pem); |
| 153 | if (certfile.empty()) { |
| 154 | LOG(ERROR) << "Unable to extract PEM certificate."; |
| 155 | } else { |
| 156 | ca_cert = certfile.value(); |
| 157 | } |
| 158 | } else if (!eap.ca_cert_nss.empty()) { |
| 159 | FilePath certfile = nss->GetDERCertfile(eap.ca_cert_nss, nss_identifier); |
| 160 | if (certfile.empty()) { |
| 161 | LOG(ERROR) << "Unable to extract DER certificate: " << eap.ca_cert_nss; |
| 162 | } else { |
| 163 | ca_cert = certfile.value(); |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | |
| 168 | typedef std::pair<const char *, const char *> KeyVal; |
| 169 | KeyVal init_propertyvals[] = { |
| 170 | KeyVal(WPASupplicant::kNetworkPropertyEapIdentity, eap.identity.c_str()), |
| 171 | KeyVal(WPASupplicant::kNetworkPropertyEapEap, eap.eap.c_str()), |
| 172 | KeyVal(WPASupplicant::kNetworkPropertyEapInnerEap, |
| 173 | eap.inner_eap.c_str()), |
| 174 | KeyVal(WPASupplicant::kNetworkPropertyEapAnonymousIdentity, |
| 175 | eap.anonymous_identity.c_str()), |
| 176 | KeyVal(WPASupplicant::kNetworkPropertyEapClientCert, |
| 177 | eap.client_cert.c_str()), |
| 178 | KeyVal(WPASupplicant::kNetworkPropertyEapPrivateKey, |
| 179 | eap.private_key.c_str()), |
| 180 | KeyVal(WPASupplicant::kNetworkPropertyEapPrivateKeyPassword, |
| 181 | eap.private_key_password.c_str()), |
| 182 | KeyVal(WPASupplicant::kNetworkPropertyEapCaCert, ca_cert.c_str()), |
| 183 | KeyVal(WPASupplicant::kNetworkPropertyEapCaPassword, |
| 184 | eap.password.c_str()), |
| 185 | KeyVal(WPASupplicant::kNetworkPropertyEapCertId, eap.cert_id.c_str()), |
| 186 | KeyVal(WPASupplicant::kNetworkPropertyEapKeyId, eap.key_id.c_str()), |
| 187 | KeyVal(WPASupplicant::kNetworkPropertyEapCaCertId, |
| 188 | eap.ca_cert_id.c_str()), |
| 189 | KeyVal(WPASupplicant::kNetworkPropertyEapSubjectMatch, |
| 190 | eap.subject_match.c_str()) |
| 191 | }; |
| 192 | |
| 193 | vector<KeyVal> propertyvals(init_propertyvals, |
| 194 | init_propertyvals + arraysize(init_propertyvals)); |
| 195 | if (eap.use_system_cas) { |
| 196 | propertyvals.push_back(KeyVal( |
| 197 | WPASupplicant::kNetworkPropertyCaPath, WPASupplicant::kCaPath)); |
| 198 | } else if (ca_cert.empty()) { |
| 199 | LOG(WARNING) << __func__ |
| 200 | << ": No certificate authorities are configured." |
| 201 | << " Server certificates will be accepted" |
| 202 | << " unconditionally."; |
| 203 | } |
| 204 | |
| 205 | if (!eap.cert_id.empty() || !eap.key_id.empty() || |
| 206 | !eap.ca_cert_id.empty()) { |
| 207 | propertyvals.push_back(KeyVal( |
| 208 | WPASupplicant::kNetworkPropertyEapPin, eap.pin.c_str())); |
| 209 | propertyvals.push_back(KeyVal( |
| 210 | WPASupplicant::kNetworkPropertyEngineId, |
| 211 | WPASupplicant::kEnginePKCS11)); |
| 212 | // We can't use the propertyvals vector for this since this argument |
| 213 | // is a uint32, not a string. |
| 214 | (*params)[WPASupplicant::kNetworkPropertyEngine].writer(). |
| 215 | append_uint32(WPASupplicant::kDefaultEngine); |
| 216 | } |
| 217 | |
| 218 | vector<KeyVal>::iterator it; |
| 219 | for (it = propertyvals.begin(); it != propertyvals.end(); ++it) { |
| 220 | if (strlen((*it).second) > 0) { |
| 221 | (*params)[(*it).first].writer().append_string((*it).second); |
| 222 | } |
| 223 | } |
| 224 | } |
mukesh agrawal | 6e27777 | 2011-09-29 15:04:23 -0700 | [diff] [blame] | 225 | |
Paul Stewart | 735eab5 | 2013-03-29 09:19:23 -0700 | [diff] [blame] | 226 | // static |
| 227 | bool WPASupplicant::ExtractRemoteCertification( |
| 228 | const std::map<std::string, DBus::Variant> &properties, |
| 229 | std::string *subject, uint32 *depth) { |
| 230 | map<string, ::DBus::Variant>::const_iterator depth_it = |
| 231 | properties.find(WPASupplicant::kInterfacePropertyDepth); |
| 232 | if (depth_it == properties.end()) { |
| 233 | LOG(ERROR) << __func__ << " no depth parameter."; |
| 234 | return false; |
| 235 | } |
| 236 | map<string, ::DBus::Variant>::const_iterator subject_it = |
| 237 | properties.find(WPASupplicant::kInterfacePropertySubject); |
| 238 | if (subject_it == properties.end()) { |
| 239 | LOG(ERROR) << __func__ << " no subject parameter."; |
| 240 | return false; |
| 241 | } |
| 242 | *depth = depth_it->second.reader().get_uint32(); |
| 243 | *subject = subject_it->second.reader().get_string(); |
| 244 | return true; |
| 245 | } |
| 246 | |
mukesh agrawal | 6e27777 | 2011-09-29 15:04:23 -0700 | [diff] [blame] | 247 | } // namespace shill |