Skip to content

Commit 63ec850

Browse files
authored
Merge pull request #14 from benwwchen/cpp0x
fix support for macOS and Linux & add EAP-MD5 CHAP method
2 parents 001c956 + fc547f7 commit 63ec850

File tree

10 files changed

+431
-28
lines changed

10 files changed

+431
-28
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Then you get `sysuh3c` executable file in `/usr/local/bin`.
1919
-u --user user account (must!)
2020
-p --password password
2121
-i --iface network interface (default is eth0)
22+
-m --method EAP-MD5 CHAP method [xor/md5] (default xor)
2223
-d --daemonize daemonize
2324
-c --colorize colorize
2425
```

src/eapauth/SConscript

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ env.StaticLibrary('eapauth',
1111
[
1212
'eapauth.cpp',
1313
'eapdef.cpp',
14-
'eaputils.cpp'
14+
'eaputils.cpp',
15+
'md5.cpp'
1516
]
1617
)

src/eapauth/eapauth.cpp

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "eapdef.h"
22
#include "eapauth.h"
33
#include "eaputils.h"
4+
#include "md5.h"
45
#include <sys/socket.h>
56
#include <sys/ioctl.h>
67
#include <sys/time.h>
@@ -18,9 +19,10 @@
1819
namespace sysuh3c {
1920

2021
EAPAuth::EAPAuth(const std::string &user_name,
21-
const std::string &password, const std::string &iface)
22+
const std::string &password, const std::string &iface,
23+
eap_method method)
2224
: eapclient(iface),
23-
user_name(user_name), user_password(password),
25+
user_name(user_name), user_password(password), md5_method(method),
2426
display_promote([this] (const std::string &os) {
2527
std::cout << os << std::endl;
2628
}),
@@ -87,10 +89,28 @@ void EAPAuth::send_response_id(uint8_t packet_id) {
8789
void EAPAuth::send_response_md5(uint8_t packet_id, const std::vector<uint8_t> &md5data) {
8890
std::array<uint8_t, 16> chap;
8991
std::string pwd(user_password);
90-
if (pwd.length() < 16)
91-
pwd.append(16 - pwd.length(), '\0');
92-
for (size_t i = 0; i < chap.size(); ++ i)
93-
chap[i] = pwd[i] ^ md5data[i];
92+
std::vector<uint8_t> chapbuf;
93+
size_t chapbuflen = 1 + pwd.length() + 16;
94+
95+
switch (md5_method) {
96+
case EAP_METHOD_XOR: // xor(password, md5data)
97+
if (pwd.length() < 16)
98+
pwd.append(16 - pwd.length(), '\0');
99+
for (size_t i = 0; i < chap.size(); ++ i)
100+
chap[i] = pwd[i] ^ md5data[i];
101+
break;
102+
case EAP_METHOD_MD5: // MD5(id + password + md5data)
103+
default:
104+
chapbuf.push_back(packet_id);
105+
chapbuf.insert(chapbuf.end(), pwd.begin(), pwd.end());
106+
chapbuf.insert(chapbuf.end(), md5data.begin(), md5data.end());
107+
108+
MD5_CTX context;
109+
MD5_Init(&context);
110+
MD5_Update(&context, &chapbuf[0], chapbuflen);
111+
MD5_Final(&chap[0], &context);
112+
break;
113+
}
94114

95115
eapol_t eapol_md5;
96116
eapol_md5.vers = EAPOL_VERSION;
@@ -104,7 +124,6 @@ void EAPAuth::send_response_md5(uint8_t packet_id, const std::vector<uint8_t> &m
104124
eapol_md5.eap->data.insert(eapol_md5.eap->data.end(), user_name.begin(), user_name.end());
105125
eapol_md5.eap->eap_len = eapol_md5.eap->get_len();
106126
eapol_md5.eapol_len = eapol_md5.get_len();
107-
108127
try {
109128
eapclient << eapol_md5;
110129
}
@@ -142,10 +161,9 @@ void EAPAuth::send_response_h3c(uint8_t packet_id) {
142161

143162
void EAPAuth::eap_handler(const eapol_t &eapol_packet) {
144163
if (eapol_packet.type != EAPOL_EAPPACKET) {
145-
status_notify(EAPAUTH_UNKNOWN_PACKET_TYPE);
164+
//status_notify(EAPAUTH_UNKNOWN_PACKET_TYPE);
146165
return;
147166
}
148-
149167
switch (eapol_packet.eap->code) {
150168
case EAP_SUCCESS:
151169
status_notify(EAPAUTH_EAP_SUCCESS);

src/eapauth/eapauth.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace sysuh3c {
1212

1313
class EAPAuth {
1414
public:
15-
EAPAuth(const std::string &, const std::string &, const std::string &);
15+
EAPAuth(const std::string &, const std::string &, const std::string &, eap_method);
1616
~EAPAuth();
1717

1818
void auth();
@@ -36,6 +36,7 @@ class EAPAuth {
3636
EAPClient eapclient;
3737
std::string user_name;
3838
std::string user_password;
39+
eap_method md5_method;
3940

4041
std::function<void(const std::string &)> display_promote;
4142
std::function<void(int statno)> status_notify;

src/eapauth/eapdef.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ struct eapol_t {
7878

7979
struct ethernet_header_t {
8080
mac_addr_t dest;
81-
mac_addr_t src[6];
81+
mac_addr_t src;
8282
uint16_t type;
8383
} __attribute__((packed));
8484

@@ -96,6 +96,11 @@ enum {
9696
EAPAUTH_AUTH_MD5
9797
};
9898

99+
enum eap_method {
100+
EAP_METHOD_XOR,
101+
EAP_METHOD_MD5
102+
};
103+
99104
inline std::string strstat(int statno) {
100105
switch (statno) {
101106
case EAPAUTH_UNKNOWN_REQUEST_TYPE:

src/eapauth/eaputils.cpp

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -83,25 +83,40 @@ EAPClient::EAPClient(const std::string &iface) {
8383
abort();
8484
}
8585

86+
recv_buf.resize(1600);
87+
8688
#elif SYSTEM_DARWIN // FOR Darwin
8789

88-
if ((bpf_fd = open("/dev/bpf1", O_RDWR)) < 0) {
89-
perror("open");
90-
abort();
90+
FILE* fp;
91+
char bpf_num_str[80];
92+
fp=popen("sysctl debug.bpf_maxdevices","r");
93+
fgets(bpf_num_str,sizeof(bpf_num_str),fp);
94+
int bpf_num = strtol(bpf_num_str + 22, NULL, 0);
95+
for (int i = 0; i < bpf_num; i++) {
96+
std::string bpf_path = "/dev/bpf" + std::to_string(i);
97+
if ((bpf_fd = open(bpf_path.c_str(), O_RDWR)) >= 0)
98+
break;
99+
if (i == bpf_num - 1) {
100+
perror("open");
101+
abort();
102+
}
91103
}
92104

93105
struct ifreq ifr;
94106
memset(&ifr, 0, sizeof(ifr));
95107
strncpy(ifr.ifr_name, iface.c_str(), sizeof(ifr.ifr_name));
96108

97109
struct bpf_program bpfpro;
98-
struct timeval timeout;
99-
size_t buf_len;
100-
if ((ioctl(bpf_fd, BIOCGBLEN, &buf_len) == -1)
101-
|| (ioctl(bpf_fd, BIOCSETIF, &ifr) == -1)
102-
|| (ioctl(bpf_fd, BIOCSETF, &bpfpro) == -1)
103-
|| (ioctl(bpf_fd, BIOCFLUSH) == -1)
104-
|| (ioctl(bpf_fd, BIOCSRTIMEOUT, &timeout) == -1)) {
110+
this->timeout.tv_sec = 30;
111+
this->timeout.tv_usec = 0;
112+
const int ci_immediate=1, cmplt = 1;
113+
size_t buf_len, set_buf_len = 128;
114+
if (ioctl(bpf_fd, BIOCSBLEN, &set_buf_len) == -1
115+
|| ioctl(bpf_fd, BIOCSETIF, &ifr) == -1
116+
|| ioctl(bpf_fd, BIOCIMMEDIATE, &ci_immediate) == -1
117+
|| ioctl(bpf_fd, BIOCSHDRCMPLT, &cmplt) == -1
118+
|| ioctl(bpf_fd, BIOCGBLEN, &buf_len) == -1
119+
|| ioctl(bpf_fd, BIOCSRTIMEOUT, &this->timeout) == -1) {
105120
perror("ioctl");
106121
close(bpf_fd);
107122
abort();
@@ -136,8 +151,9 @@ EAPClient::EAPClient(const std::string &iface) {
136151
memcpy(mac_addr, ptr, sizeof(mac_addr));
137152
delete []macbuf;
138153

139-
this->timeout.tv_sec = 30;
140-
this->timeout.tv_usec = 0;
154+
// save mac address
155+
memcpy(this->mac_addr, mac_addr, 6);
156+
141157
#else
142158
#error SYSUH3C doesn't support your platform.
143159
#endif
@@ -155,6 +171,7 @@ EAPClient::EAPClient(const std::string &iface) {
155171
copy(begin(mac_addr), end(mac_addr), itr);
156172
uint16_t etype = htons(ETHERTYPE_PAE);
157173
*(uint16_t *)(ethernet_header.data() + sizeof(PAE_GROUP_ADDR) + sizeof(mac_addr)) = etype;
174+
158175
}
159176

160177
EAPClient::~EAPClient() {
@@ -183,6 +200,8 @@ EAPClient &EAPClient::recv(eapol_t &eapol) {
183200
(struct sockaddr *) &sock_addr, &sock_addr_len)) <= 0) {
184201
throw EAPAuthException("Socket recv error");
185202
}
203+
// Remove header
204+
uint8_t *buf = recv_buf.data() + sizeof(ethernet_header_t);
186205
#elif SYSTEM_DARWIN
187206
fd_set readset;
188207
FD_ZERO(&readset);
@@ -197,10 +216,18 @@ EAPClient &EAPClient::recv(eapol_t &eapol) {
197216
if ((len = read(bpf_fd, recv_buf.data(), recv_buf.size())) == -1) {
198217
throw EAPAuthException("BPF read error");
199218
}
200-
#endif
201219

220+
// check mac address and header
221+
ethernet_header_t *ethernet_header = (ethernet_header_t *)(recv_buf.data() + 18);
222+
if (memcmp(ethernet_header->dest, this->mac_addr, sizeof(mac_addr_t)) != 0
223+
|| ethernet_header->type != 0x8e88) {
224+
eapol.type = -1;
225+
return *this;
226+
}
202227
// Remove header
203-
uint8_t *buf = recv_buf.data() + sizeof(ethernet_header_t);
228+
uint8_t *buf = recv_buf.data() + 18 + sizeof(ethernet_header_t);
229+
#endif
230+
204231
if (len - sizeof(ethernet_header_t) == 0) return *this;
205232

206233
eapol.vers = buf[0];

src/eapauth/eaputils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class EAPClient {
5959
struct sockaddr_ll sock_addr;
6060
#elif SYSTEM_DARWIN
6161
struct sockaddr_dl sock_addr;
62+
mac_addr_t mac_addr;
6263
int bpf_fd;
6364
struct timeval timeout;
6465
#endif

0 commit comments

Comments
 (0)