void auth_finished (BSocksClient *o) { // allocate request buffer bsize_t size = bsize_fromsize(sizeof(struct socks_request_header)); switch (o->dest_addr.type) { case BADDR_TYPE_IPV4: size = bsize_add(size, bsize_fromsize(sizeof(struct socks_addr_ipv4))); break; case BADDR_TYPE_IPV6: size = bsize_add(size, bsize_fromsize(sizeof(struct socks_addr_ipv6))); break; } if (!reserve_buffer(o, size)) { report_error(o, BSOCKSCLIENT_EVENT_ERROR); return; } // write request struct socks_request_header header; header.ver = hton8(SOCKS_VERSION); header.cmd = hton8(SOCKS_CMD_CONNECT); header.rsv = hton8(0); switch (o->dest_addr.type) { case BADDR_TYPE_IPV4: { header.atyp = hton8(SOCKS_ATYP_IPV4); struct socks_addr_ipv4 addr; addr.addr = o->dest_addr.ipv4.ip; addr.port = o->dest_addr.ipv4.port; memcpy(o->buffer + sizeof(header), &addr, sizeof(addr)); } break; case BADDR_TYPE_IPV6: { header.atyp = hton8(SOCKS_ATYP_IPV6); struct socks_addr_ipv6 addr; memcpy(addr.addr, o->dest_addr.ipv6.ip, sizeof(o->dest_addr.ipv6.ip)); addr.port = o->dest_addr.ipv6.port; memcpy(o->buffer + sizeof(header), &addr, sizeof(addr)); } break; default: ASSERT(0); } memcpy(o->buffer, &header, sizeof(header)); // send request PacketPassInterface_Sender_Send(o->control.send_if, (uint8_t *)o->buffer, size.value); // set state o->state = STATE_SENDING_REQUEST; }
int init_info (struct instance *o, int have_bssid, const uint8_t *bssid, const uint8_t *ssid, size_t ssid_len) { ASSERT(!o->have_info) // set bssid o->info_have_bssid = have_bssid; if (have_bssid) { memcpy(o->info_bssid, bssid, 6); } // set ssid if (!(o->info_ssid = BAllocSize(bsize_add(bsize_fromsize(ssid_len), bsize_fromsize(1))))) { ModuleLog(o->i, BLOG_ERROR, "BAllocSize failed"); return 0; } memcpy(o->info_ssid, ssid, ssid_len); o->info_ssid[ssid_len] = '\0'; // set have info o->have_info = 1; return 1; }
static void concatlist_eval (NCDCall call) { NCDValRef args_list; if (!ncd_eval_func_args(&call, NCDCall_ResMem(&call), &args_list)) { return; } size_t arg_count = NCDVal_ListCount(args_list); bsize_t elem_count = bsize_fromsize(0); for (size_t i = 0; i < arg_count; i++) { NCDValRef arg = NCDVal_ListGet(args_list, i); if (!NCDVal_IsList(arg)) { return FunctionLog(&call, BLOG_ERROR, "concatlist: argument is not a list"); } elem_count = bsize_add(elem_count, bsize_fromsize(NCDVal_ListCount(arg))); } if (elem_count.is_overflow) { return FunctionLog(&call, BLOG_ERROR, "concatlist: count overflow"); } NCDValRef res = NCDVal_NewList(NCDCall_ResMem(&call), elem_count.value); if (NCDVal_IsInvalid(res)) { return; } for (size_t i = 0; i < arg_count; i++) { NCDValRef arg = NCDVal_ListGet(args_list, i); size_t arg_list_count = NCDVal_ListCount(arg); for (size_t j = 0; j < arg_list_count; j++) { NCDValRef copy = NCDVal_NewCopy(NCDCall_ResMem(&call), NCDVal_ListGet(arg, j)); if (NCDVal_IsInvalid(copy)) { return; } if (!NCDVal_ListAppend(res, copy)) { return; } } } NCDCall_SetResult(&call, res); }
void send_handler_done (BSocksClient *o) { DebugObject_Access(&o->d_obj); ASSERT(o->buffer) switch (o->state) { case STATE_SENDING_HELLO: { BLog(BLOG_DEBUG, "sent hello"); // allocate buffer for receiving hello bsize_t size = bsize_fromsize(sizeof(struct socks_server_hello)); if (!reserve_buffer(o, size)) { goto fail; } // receive hello start_receive(o, (uint8_t *)o->buffer, size.value); // set state o->state = STATE_SENT_HELLO; } break; case STATE_SENDING_REQUEST: { BLog(BLOG_DEBUG, "sent request"); // allocate buffer for receiving reply bsize_t size = bsize_add( bsize_fromsize(sizeof(struct socks_reply_header)), bsize_max(bsize_fromsize(sizeof(struct socks_addr_ipv4)), bsize_fromsize(sizeof(struct socks_addr_ipv6))) ); if (!reserve_buffer(o, size)) { goto fail; } // receive reply header start_receive(o, (uint8_t *)o->buffer, sizeof(struct socks_reply_header)); // set state o->state = STATE_SENT_REQUEST; } break; case STATE_SENDING_PASSWORD: { BLog(BLOG_DEBUG, "send password"); // allocate buffer for receiving reply bsize_t size = bsize_fromsize(2); if (!reserve_buffer(o, size)) { goto fail; } // receive reply header start_receive(o, (uint8_t *)o->buffer, size.value); // set state o->state = STATE_SENT_PASSWORD; } break; default: ASSERT(0); } return; fail: report_error(o, BSOCKSCLIENT_EVENT_ERROR); }
void recv_handler_done (BSocksClient *o, int data_len) { ASSERT(data_len >= 0) ASSERT(data_len <= o->control.recv_total - o->control.recv_len) DebugObject_Access(&o->d_obj); o->control.recv_len += data_len; if (o->control.recv_len < o->control.recv_total) { do_receive(o); return; } switch (o->state) { case STATE_SENT_HELLO: { BLog(BLOG_DEBUG, "received hello"); struct socks_server_hello imsg; memcpy(&imsg, o->buffer, sizeof(imsg)); if (ntoh8(imsg.ver) != SOCKS_VERSION) { BLog(BLOG_NOTICE, "wrong version"); goto fail; } size_t auth_index; for (auth_index = 0; auth_index < o->num_auth_info; auth_index++) { if (o->auth_info[auth_index].auth_type == ntoh8(imsg.method)) { break; } } if (auth_index == o->num_auth_info) { BLog(BLOG_NOTICE, "server didn't accept any authentication method"); goto fail; } const struct BSocksClient_auth_info *ai = &o->auth_info[auth_index]; switch (ai->auth_type) { case SOCKS_METHOD_NO_AUTHENTICATION_REQUIRED: { BLog(BLOG_DEBUG, "no authentication"); auth_finished(o); } break; case SOCKS_METHOD_USERNAME_PASSWORD: { BLog(BLOG_DEBUG, "password authentication"); if (ai->password.username_len == 0 || ai->password.username_len > 255 || ai->password.password_len == 0 || ai->password.password_len > 255 ) { BLog(BLOG_NOTICE, "invalid username/password length"); goto fail; } // allocate password packet bsize_t size = bsize_fromsize(1 + 1 + ai->password.username_len + 1 + ai->password.password_len); if (!reserve_buffer(o, size)) { goto fail; } // write password packet char *ptr = o->buffer; *ptr++ = 1; *ptr++ = ai->password.username_len; memcpy(ptr, ai->password.username, ai->password.username_len); ptr += ai->password.username_len; *ptr++ = ai->password.password_len; memcpy(ptr, ai->password.password, ai->password.password_len); ptr += ai->password.password_len; // start sending PacketPassInterface_Sender_Send(o->control.send_if, (uint8_t *)o->buffer, size.value); // set state o->state = STATE_SENDING_PASSWORD; } break; default: ASSERT(0); } } break; case STATE_SENT_REQUEST: { BLog(BLOG_DEBUG, "received reply header"); struct socks_reply_header imsg; memcpy(&imsg, o->buffer, sizeof(imsg)); if (ntoh8(imsg.ver) != SOCKS_VERSION) { BLog(BLOG_NOTICE, "wrong version"); goto fail; } if (ntoh8(imsg.rep) != SOCKS_REP_SUCCEEDED) { BLog(BLOG_NOTICE, "reply not successful"); goto fail; } int addr_len; switch (ntoh8(imsg.atyp)) { case SOCKS_ATYP_IPV4: addr_len = sizeof(struct socks_addr_ipv4); break; case SOCKS_ATYP_IPV6: addr_len = sizeof(struct socks_addr_ipv6); break; default: BLog(BLOG_NOTICE, "reply has unknown address type"); goto fail; } // receive the rest of the reply start_receive(o, (uint8_t *)o->buffer + sizeof(imsg), addr_len); // set state o->state = STATE_RECEIVED_REPLY_HEADER; } break; case STATE_SENT_PASSWORD: { BLog(BLOG_DEBUG, "received password reply"); if (o->buffer[0] != 1) { BLog(BLOG_NOTICE, "password reply has unknown version"); goto fail; } if (o->buffer[1] != 0) { BLog(BLOG_NOTICE, "password reply is negative"); goto fail; } auth_finished(o); } break; case STATE_RECEIVED_REPLY_HEADER: { BLog(BLOG_DEBUG, "received reply rest"); // free buffer BFree(o->buffer); o->buffer = NULL; // free control I/O free_control_io(o); // init up I/O init_up_io(o); // set state o->state = STATE_UP; // call handler o->handler(o->user, BSOCKSCLIENT_EVENT_UP); return; } break; default: ASSERT(0); } return; fail: report_error(o, BSOCKSCLIENT_EVENT_ERROR); }
void connector_handler (BSocksClient* o, int is_error) { DebugObject_Access(&o->d_obj); ASSERT(o->state == STATE_CONNECTING) // check connection result if (is_error) { // PSIPHON // BLog(BLOG_ERROR, "connection failed"); BLog(BLOG_WARNING, "connection failed"); goto fail0; } // init connection if (!BConnection_Init(&o->con, BConnection_source_connector(&o->connector), o->reactor, o, (BConnection_handler)connection_handler)) { BLog(BLOG_ERROR, "BConnection_Init failed"); goto fail0; } BLog(BLOG_DEBUG, "connected"); // init control I/O init_control_io(o); // check number of methods if (o->num_auth_info == 0 || o->num_auth_info > 255) { BLog(BLOG_ERROR, "invalid number of authentication methods"); goto fail1; } // allocate buffer for sending hello bsize_t size = bsize_add( bsize_fromsize(sizeof(struct socks_client_hello_header)), bsize_mul( bsize_fromsize(o->num_auth_info), bsize_fromsize(sizeof(struct socks_client_hello_method)) ) ); if (!reserve_buffer(o, size)) { goto fail1; } // write hello header struct socks_client_hello_header header; header.ver = hton8(SOCKS_VERSION); header.nmethods = hton8(o->num_auth_info); memcpy(o->buffer, &header, sizeof(header)); // write hello methods for (size_t i = 0; i < o->num_auth_info; i++) { struct socks_client_hello_method method; method.method = hton8(o->auth_info[i].auth_type); memcpy(o->buffer + sizeof(header) + i * sizeof(method), &method, sizeof(method)); } // send PacketPassInterface_Sender_Send(o->control.send_if, (uint8_t *)o->buffer, size.value); // set state o->state = STATE_SENDING_HELLO; return; fail1: free_control_io(o); BConnection_Free(&o->con); fail0: report_error(o, BSOCKSCLIENT_EVENT_ERROR); return; }
void NCDConfigTokenizer_Tokenize (char *str, size_t left, NCDConfigTokenizer_output output, void *user) { size_t line = 1; size_t line_char = 1; while (left > 0) { size_t l; int error = 0; int token; void *token_val = NULL; size_t token_len = 0; if (*str == '#') { l = 1; while (l < left && str[l] != '\n') { l++; } token = 0; } else if (l = data_begins_with(str, left, "{")) { token = NCD_TOKEN_CURLY_OPEN; } else if (l = data_begins_with(str, left, "}")) { token = NCD_TOKEN_CURLY_CLOSE; } else if (l = data_begins_with(str, left, "(")) { token = NCD_TOKEN_ROUND_OPEN; } else if (l = data_begins_with(str, left, ")")) { token = NCD_TOKEN_ROUND_CLOSE; } else if (l = data_begins_with(str, left, ";")) { token = NCD_TOKEN_SEMICOLON; } else if (l = data_begins_with(str, left, ".")) { token = NCD_TOKEN_DOT; } else if (l = data_begins_with(str, left, ",")) { token = NCD_TOKEN_COMMA; } else if (l = data_begins_with(str, left, ":")) { token = NCD_TOKEN_COLON; } else if (l = data_begins_with(str, left, "[")) { token = NCD_TOKEN_BRACKET_OPEN; } else if (l = data_begins_with(str, left, "]")) { token = NCD_TOKEN_BRACKET_CLOSE; } else if (l = data_begins_with(str, left, "->")) { token = NCD_TOKEN_ARROW; } else if (l = data_begins_with(str, left, "If")) { token = NCD_TOKEN_IF; } else if (l = data_begins_with(str, left, "Elif")) { token = NCD_TOKEN_ELIF; } else if (l = data_begins_with(str, left, "elif")) { token = NCD_TOKEN_ELIF; } else if (l = data_begins_with(str, left, "Else")) { token = NCD_TOKEN_ELSE; } else if (l = data_begins_with(str, left, "else")) { token = NCD_TOKEN_ELSE; } else if (l = data_begins_with(str, left, "Foreach")) { token = NCD_TOKEN_FOREACH; } else if (l = data_begins_with(str, left, "As")) { token = NCD_TOKEN_AS; } else if (l = data_begins_with(str, left, "include_guard")) { token = NCD_TOKEN_INCLUDE_GUARD; } else if (l = data_begins_with(str, left, "include")) { token = NCD_TOKEN_INCLUDE; } else if (is_name_first_char(*str)) { l = 1; while (l < left && is_name_char(str[l])) { l++; } // allocate buffer bsize_t bufsize = bsize_add(bsize_fromsize(l), bsize_fromint(1)); char *buf; if (bufsize.is_overflow || !(buf = malloc(bufsize.value))) { BLog(BLOG_ERROR, "malloc failed"); error = 1; goto out; } // copy and terminate memcpy(buf, str, l); buf[l] = '\0'; if (!strcmp(buf, "process")) { token = NCD_TOKEN_PROCESS; free(buf); } else if (!strcmp(buf, "template")) { token = NCD_TOKEN_TEMPLATE; free(buf); } else { token = NCD_TOKEN_NAME; token_val = buf; token_len = l; } } else if (*str == '"') do { // init string ExpString estr; if (!ExpString_Init(&estr)) { BLog(BLOG_ERROR, "ExpString_Init failed"); goto string_fail0; } // skip start quote l = 1; // decode string while (l < left) { uint8_t dec_ch; // get character if (str[l] == '\\') { if (left - l < 2) { BLog(BLOG_ERROR, "escape character found in string but nothing follows"); goto string_fail1; } size_t extra = 0; switch (str[l + 1]) { case '\'': case '\"': case '\\': case '\?': dec_ch = str[l + 1]; break; case 'a': dec_ch = '\a'; break; case 'b': dec_ch = '\b'; break; case 'f': dec_ch = '\f'; break; case 'n': dec_ch = '\n'; break; case 'r': dec_ch = '\r'; break; case 't': dec_ch = '\t'; break; case 'v': dec_ch = '\v'; break; case '0': dec_ch = 0; break; case 'x': { if (left - l < 4) { BLog(BLOG_ERROR, "hexadecimal escape found in string but too little characters follow"); goto string_fail1; } uintmax_t hex_val; if (!parse_unsigned_hex_integer_bin(&str[l + 2], 2, &hex_val)) { BLog(BLOG_ERROR, "hexadecimal escape found in string but two hex characters don't follow"); goto string_fail1; } dec_ch = hex_val; extra = 2; } break; default: BLog(BLOG_ERROR, "bad escape sequence in string"); goto string_fail1; } l += 2 + extra; } else if (str[l] == '"') { break; } else { dec_ch = str[l]; l++; } // append character to string if (!ExpString_AppendByte(&estr, dec_ch)) { BLog(BLOG_ERROR, "ExpString_AppendChar failed"); goto string_fail1; } } // make sure ending quote was found if (l == left) { BLog(BLOG_ERROR, "missing ending quote for string"); goto string_fail1; } // skip ending quote l++; token = NCD_TOKEN_STRING; token_val = ExpString_Get(&estr); token_len = ExpString_Length(&estr); break; string_fail1: ExpString_Free(&estr); string_fail0: error = 1; } while (0); else if (is_space_char(*str)) { token = 0; l = 1; } else { BLog(BLOG_ERROR, "unrecognized character"); error = 1; } out: // report error if (error) { output(user, NCD_ERROR, NULL, 0, line, line_char); return; } // output token if (token) { if (!output(user, token, token_val, token_len, line, line_char)) { return; } } // update line/char counters for (size_t i = 0; i < l; i++) { if (str[i] == '\n') { line++; line_char = 1; } else { line_char++; } } str += l; left -= l; } output(user, NCD_EOF, NULL, 0, line, line_char); }
void NCDConfigTokenizer_Tokenize (char *str, size_t left, NCDConfigTokenizer_output output, void *user) { size_t line = 1; size_t line_char = 1; while (left > 0) { size_t l; int error = 0; int token; void *token_val = NULL; if (*str == '#') { l = 1; while (l < left && str[l] != '\n') { l++; } token = 0; } else if (l = data_begins_with(str, left, "{")) { token = NCD_TOKEN_CURLY_OPEN; } else if (l = data_begins_with(str, left, "}")) { token = NCD_TOKEN_CURLY_CLOSE; } else if (l = data_begins_with(str, left, "(")) { token = NCD_TOKEN_ROUND_OPEN; } else if (l = data_begins_with(str, left, ")")) { token = NCD_TOKEN_ROUND_CLOSE; } else if (l = data_begins_with(str, left, ";")) { token = NCD_TOKEN_SEMICOLON; } else if (l = data_begins_with(str, left, ".")) { token = NCD_TOKEN_DOT; } else if (l = data_begins_with(str, left, ",")) { token = NCD_TOKEN_COMMA; } else if (l = data_begins_with(str, left, ":")) { token = NCD_TOKEN_COLON; } else if (l = data_begins_with(str, left, "[")) { token = NCD_TOKEN_BRACKET_OPEN; } else if (l = data_begins_with(str, left, "]")) { token = NCD_TOKEN_BRACKET_CLOSE; } else if (l = data_begins_with(str, left, "->")) { token = NCD_TOKEN_ARROW; } else if (is_name_first_char(*str)) { l = 1; while (l < left && is_name_char(str[l])) { l++; } // allocate buffer bsize_t bufsize = bsize_add(bsize_fromsize(l), bsize_fromint(1)); char *buf; if (bufsize.is_overflow || !(buf = malloc(bufsize.value))) { BLog(BLOG_ERROR, "malloc failed"); error = 1; goto out; } // copy and terminate memcpy(buf, str, l); buf[l] = '\0'; if (!strcmp(buf, "process")) { token = NCD_TOKEN_PROCESS; free(buf); } else if (!strcmp(buf, "template")) { token = NCD_TOKEN_TEMPLATE; free(buf); } else { token = NCD_TOKEN_NAME; token_val = buf; } } else if (*str == '"') do { // init string ExpString estr; if (!ExpString_Init(&estr)) { BLog(BLOG_ERROR, "ExpString_Init failed"); goto string_fail0; } // skip start quote l = 1; // decode string while (l < left) { char dec_ch; // get character if (str[l] == '\\') { if (left - l < 2) { BLog(BLOG_ERROR, "escape character found in string but nothing follows"); goto string_fail1; } dec_ch = str[l + 1]; l += 2; } else if (str[l] == '"') { break; } else { dec_ch = str[l]; l++; } // string cannot contain zeros bytes if (dec_ch == '\0') { BLog(BLOG_ERROR, "string contains zero byte"); goto string_fail1; } // append character to string if (!ExpString_AppendChar(&estr, dec_ch)) { BLog(BLOG_ERROR, "ExpString_AppendChar failed"); goto string_fail1; } } // make sure ending quote was found if (l == left) { BLog(BLOG_ERROR, "missing ending quote for string"); goto string_fail1; } // skip ending quote l++; token = NCD_TOKEN_STRING; token_val = ExpString_Get(&estr); break; string_fail1: ExpString_Free(&estr); string_fail0: error = 1; } while (0); else if (is_space_char(*str)) { token = 0; l = 1; } else { BLog(BLOG_ERROR, "unrecognized character"); error = 1; } out: // report error if (error) { output(user, NCD_ERROR, NULL, line, line_char); return; } // output token if (token) { if (!output(user, token, token_val, line, line_char)) { return; } } // update line/char counters for (size_t i = 0; i < l; i++) { if (str[i] == '\n') { line++; line_char = 1; } else { line_char++; } } str += l; left -= l; } output(user, NCD_EOF, NULL, line, line_char); }