static void handle_ctcp_request(irc_session_t *session, irc_parser_result_t *result) { char ctcp_buf[LIBIRC_BUFFER_SIZE]; char **params = result->params; size_t msglen = strlen(result->params[1]); msglen -= 2; if (msglen > sizeof (ctcp_buf) - 1) msglen = sizeof (ctcp_buf) - 1; memcpy(ctcp_buf, params[1] + 1, msglen); ctcp_buf[msglen] = '\0'; DBG_OK("ctcp req recvd! %s", ctcp_buf); if (is_dcc_request(ctcp_buf)) { libirc_dcc_request(session, result, ctcp_buf); } else if (is_action_message(ctcp_buf) && session->callbacks.event_ctcp_action) { // this removes "ACTION" in front of the message char *buf = calloc(strlen(ctcp_buf)+1, sizeof(char)); memcpy(buf, ctcp_buf+7, strlen(ctcp_buf)-7); params[1] = buf; result->num_params = 2; (*session->callbacks.event_ctcp_action) (session, "ACTION", result); } else { char *buf = calloc(strlen(ctcp_buf)+1, sizeof(char)); memcpy(buf, ctcp_buf, strlen(ctcp_buf)); params[0] = buf; result->num_params = 1; if (session->callbacks.event_ctcp_req) (*session->callbacks.event_ctcp_req) (session, "CTCP", result); } }
static void send_current_file_offset_to_sender (irc_session_t *session, irc_dcc_session_t *dcc) { int sentBytes, err = 0; // we convert out irc_dcc_size_t to uint32_t, because it's defined like that in dcc... uint32_t confirmSizeNetworkOrder = htobe32(dcc->file_confirm_offset); size_t offset = sizeof(confirmSizeNetworkOrder); #ifdef ENABLE_SSL if (dcc->ssl == 0) sentBytes = socket_send(&dcc->sock, &confirmSizeNetworkOrder, offset); else { int sslError = 0; sentBytes = ssl_write_wrapper(session, dcc, &confirmSizeNetworkOrder, offset, &sslError); if (sslError == SSL_ERROR_WANT_READ) { dcc->state = LIBIRC_STATE_CONNECTED; return; } else if (sslError == SSL_ERROR_WANT_WRITE) { return; } } #else sentBytes = socket_send(&dcc->sock, &confirmSizeNetworkOrder, offset); #endif if (unlikely(sentBytes < 0)) { DBG_WARN("err send length < 0"); DBG_WARN("error msg: %s\n", strerror(errno)); err = LIBIRC_ERR_WRITE; } else if (unlikely(sentBytes == 0)) { err = LIBIRC_ERR_CLOSED; } else { if (unlikely(dcc->received_file_size == dcc->file_confirm_offset)) { DBG_OK("dcc->received_file_size == dcc->file_confirm_offset"); libirc_mutex_unlock(&session->mutex_dcc); (*dcc->cb)(session, dcc->id, 0, dcc->ctx, 0, 0); libirc_mutex_lock(&session->mutex_dcc); libirc_dcc_destroy_nolock(session, dcc->id); } else { /* Continue to receive the file */ dcc->state = LIBIRC_STATE_CONNECTED; } } /* * If error arises somewhere above, we inform the caller * of failure, and destroy this session. */ if (unlikely(err)) { libirc_mutex_unlock(&session->mutex_dcc); (*dcc->cb)(session, dcc->id, err, dcc->ctx, 0, 0); libirc_mutex_lock(&session->mutex_dcc); //libirc_dcc_destroy_nolock (ircsession, dcc->id); } }
static void optimizeSocketBufferSize(const irc_dcc_session_t *dcc) { int bufferSize = 0; socklen_t bufSizeLen = sizeof(int); getsockopt(dcc->sock, SOL_SOCKET, SO_RCVBUF, &bufferSize, &bufSizeLen); bufferSize *= 2; bufferSize *= 16; DBG_OK("got buffer size of %d!", bufferSize); setsockopt(dcc->sock, SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize)); }
static void accept_dcc_send(irc_session_t * session, const char * nick, const char * req, char *filename, unsigned long ip, irc_dcc_size_t size, unsigned short port, int ssl) { DBG_OK("---- got dcc send req: %s ---", req); if (session->callbacks.event_dcc_send_req) { irc_dcc_session_t * dcc; int err = libirc_new_dcc_session(session, ip, port, 0, &dcc, ssl); if (err) { session->lasterror = err; return; } (*session->callbacks.event_dcc_send_req) (session, nick, inet_ntoa(dcc->remote_addr.sin_addr), filename, size, dcc->id); dcc->received_file_size = size; } }
int init_syn_psam(int slot, int baud, u_short adfid, u_char *keyid) { DBG("Init terminal PSAM ..."); if (init_psam(&pc, slot, baud)) { DBG_NT(" failed to alloc mem!\n"); return -1; } int ret = 0; if (ret = init_sam_card(pc)) { DBG_NT(" failed, init SAM card!\n"); } else if (init_descrypt_psam(pc, adfid, keyid)) { DBG_NT(" failed, check key!\n"); } if (ret) { if (pc) { delete_psam_cos(pc); pc = NULL; } return -1; } if (check_terminal_type(pc)) { DBG_NT(" failed, terminal type!\n"); return -1; } DBG_OK(); return 0; }
int irc_dcc_resume(irc_session_t * session, irc_dcc_t dccid, void * ctx, irc_dcc_callback_t callback, const char *nick, irc_dcc_size_t filePosition) { irc_dcc_session_t * dcc = libirc_find_dcc_session(session, dccid, 1); if (!dcc) return 1; if (dcc->state != LIBIRC_STATE_INIT) { session->lasterror = LIBIRC_ERR_STATE; libirc_mutex_unlock(&session->mutex_dcc); return 1; } dcc->cb = callback; dcc->ctx = ctx; // ctcp msg to bot char buf[512]; snprintf(buf, sizeof(buf), "DCC RESUME file.ext %hu %" IRC_DCC_SIZE_T_FORMAT "", ntohs(dcc->remote_addr.sin_port), filePosition); DBG_OK("%s", buf); irc_cmd_ctcp_request(session, nick, buf); dcc->state = LIBIRC_STATE_WAITING_FOR_RESUME_ACK; libirc_mutex_unlock(&session->mutex_dcc); return 0; }
/* * adf: YKT app id * tsn: terminal code */ int init_pbocsam_card(int slot, int baud, char *adf, u_char *tsn) { DBG("Init pboc PSAM..."); if (NULL == adf || NULL == tsn) { DBG_NT(" null of AID or Terminal Code!\n"); return -1; } if (!pboc) { if (init_psam(&pboc, slot, baud)) { DBG_NT(" failed to alloc mem!\n"); goto err; } if (init_sam_card(pboc)) { DBG_NT(" failed to init SAM card!\n"); goto free_err; } } else if (reset_psam_card(pboc)) { DBG_NT(" failed to reset SAM card!\n"); goto err; } if (psam_factory(pboc) == -1) { DBG_NT("Unknow PBOC SAM card!\n"); goto free_err; } /* Check terminal serial that saved in PSAM */ int ret; if (-1 == (ret = psam_read_binary(pboc, &resp, PBOC_TERM_FID, 0, PBOC_TERM_FLEN))) { DBG_NT(" Read terminal info file error!\n"); return -1; } /* DBG_MEM("PSAM PBOC tsn:", resp, ret); */ if (memcmp(tsn, resp, PBOC_TERM_FLEN)) { /* DBG_MEM("Update terminal serial to PSAM. New tsn:", tsn, 6); */ if (-1 == psam_update_binary(pboc, &resp, tsn, PBOC_TERM_FID, 0, PBOC_TERM_FLEN)) { DBG("Update terminal serial failed!\n"); return -1; } } #ifdef __PBOC_TEST adf = "SZDXCARD0000001"; #endif /* Select PBOC ADF */ /* DBG("Select PBOC APP using %s\n", adf); */ if (-1 == psam_select_name(pboc, &resp, adf)) { DBG("Select PBOC app in PSAM error!\n"); return -1; } memset(pboc_adf, 0, sizeof(pboc_adf)); strncpy(pboc_adf, adf, sizeof(pboc_adf) - 1); DBG_OK(); return 0; free_err: delete_psam_cos(pboc); pboc = NULL; err: return -1; }
int irc_dcc_accept(irc_session_t * session, irc_dcc_t dccid, void * ctx, irc_dcc_callback_t callback) { irc_dcc_session_t * dcc = libirc_find_dcc_session(session, dccid, 1); if (!dcc) return 1; if (dcc->state != LIBIRC_STATE_INIT) { session->lasterror = LIBIRC_ERR_STATE; libirc_mutex_unlock(&session->mutex_dcc); return 1; } dcc->cb = callback; dcc->ctx = ctx; DBG_OK("going to socket_connect!"); // Initiate the connect if (socket_connect(&dcc->sock, (struct sockaddr *) &dcc->remote_addr, sizeof (dcc->remote_addr))) { libirc_dcc_destroy_nolock(session, dccid); libirc_mutex_unlock(&session->mutex_dcc); session->lasterror = LIBIRC_ERR_CONNECT; return 1; } #ifdef ENABLE_SSL if (dcc->ssl == 1) { DBG_OK("using ssl!"); while (1) { int err = SSL_connect(dcc->ssl_ctx); if (err <= 0) { int ssl_err = SSL_get_error(dcc->ssl_ctx, err); if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE) { continue; } else { print_ssl_error_stack(); session->lasterror = LIBIRC_ERR_CONNECT; return 1; } } DBG_OK("ssl_connect succeded!"); break; } const char *ciphers_used = "None"; ciphers_used = SSL_get_cipher_name(dcc->ssl_ctx); logprintf(LOG_INFO, "using cipher suite: %s for dcc connection", ciphers_used); } #endif DBG_OK("connect succeded2!"); dcc->state = LIBIRC_STATE_CONNECTING; #ifdef ENABLE_SSL if (dcc->ssl) { dcc->state = LIBIRC_STATE_CONNECTED; } #endif libirc_mutex_unlock(&session->mutex_dcc); return 0; }
static void libirc_dcc_request(irc_session_t * session, irc_parser_result_t *result, const char * req) { char filenamebuf[LIBIRC_BUFFER_SIZE+1]; unsigned long ip; unsigned long token; irc_dcc_size_t size; unsigned short port; filenamebuf[LIBIRC_BUFFER_SIZE] = (char) 0; DBG_OK("---- got dcc req: %s ---", req); if (!isValidRequestFromNick(result->nick)) { DBG_WARN("received unknown dcc req from nick %s. ignoring that request!", result->nick); return; } if (sscanf(req, "DCC SEND %"LIBIRC_BUFFER_SIZE_STR"s %lu 0 %" IRC_DCC_SIZE_T_FORMAT" %lu", filenamebuf, &ip, &size, &token) == 4) { accept_reverse_dcc_send(session, result->nick, req, filenamebuf, ip, size, token, NO_SSL); return; } if (sscanf(req, "DCC SEND %"LIBIRC_BUFFER_SIZE_STR"s %lu %hu %" IRC_DCC_SIZE_T_FORMAT, filenamebuf, &ip, &port, &size) == 4) { accept_dcc_send(session, result->nick, req, filenamebuf, ip, size, port, NO_SSL); return; } /*this matches file names that contain spaces and are are delimited by quotes, so for example "This is a really long file name with spaces" would match*/ else if (sscanf(req, "DCC SEND \"%"LIBIRC_BUFFER_SIZE_STR"[^\"]\" %lu %hu %" IRC_DCC_SIZE_T_FORMAT, filenamebuf, &ip, &port, &size) == 4) { accept_dcc_send(session, result->nick, req, filenamebuf, ip, size, port, NO_SSL); return; } else if (sscanf(req, "DCC SEND %"LIBIRC_BUFFER_SIZE_STR"s %lu %hu", filenamebuf, &ip, &port) == 3) { size = 0; accept_dcc_send(session, result->nick, req, filenamebuf, ip, size, port, NO_SSL); return; } #if defined (ENABLE_SSL) else if (sscanf(req, "DCC SSEND %"LIBIRC_BUFFER_SIZE_STR"s %lu %hu %" IRC_DCC_SIZE_T_FORMAT, filenamebuf, &ip, &port, &size) == 4) { accept_dcc_send(session, result->nick, req, filenamebuf, ip, size, port, USE_SSL); return; } #endif else if (sscanf(req, "DCC ACCEPT file.ext %hu %" IRC_DCC_SIZE_T_FORMAT, &port, &size) == 2) { DBG_OK("---- got dcc accept req: %hu %" IRC_DCC_SIZE_T_FORMAT " ---", port, size); irc_dcc_session_t * dcc; dcc = libirc_find_dcc_session_by_port(session, port, 1); if (dcc == NULL) { DBG_WARN("cant find open dcc session with port = %hu!", port); return; } if (dcc->state != LIBIRC_STATE_WAITING_FOR_RESUME_ACK) { DBG_WARN("dcc->state != LIBIRC_STATE_WAITING_FOR_RESUME_ACK"); return; } dcc->state = LIBIRC_STATE_INIT; dcc->file_confirm_offset = size; libirc_mutex_unlock(&session->mutex_dcc); (*dcc->cb) (session, dcc->id, 1, dcc->ctx, NULL, size); return; } DBG_ERR("BUG: Unhandled DCC message: %s", req); }
static int libirc_new_dcc_session(irc_session_t * session, unsigned long ip, unsigned short port, void * ctx, irc_dcc_session_t ** pdcc, int ssl) { irc_dcc_session_t * dcc = malloc(sizeof (irc_dcc_session_t)); if (!dcc) return LIBIRC_ERR_NOMEM; // setup memset(dcc, 0, sizeof (irc_dcc_session_t)); dcc->dccsend_file_fp = 0; if (libirc_mutex_init(&dcc->mutex_outbuf)) goto cleanup_exit_error; if (socket_create(PF_INET, SOCK_STREAM, &dcc->sock)) goto cleanup_exit_error; // make socket non-blocking, so connect() call won't block if (socket_make_nonblocking(&dcc->sock)) goto cleanup_exit_error; //optimizeSocketBufferSize(dcc); #if defined (ENABLE_SSL) dcc->ssl = 0; if (ssl) { dcc->ssl = 1; if (!isSslIntitialized()) { DBG_OK("need to init ssl context!"); int ret = initSslContext(session); if (ret != 0) { DBG_ERR("ssl context cant be inited!"); exit(-1); } } dcc->ssl_ctx = SSL_new(ssl_context); SSL_set_fd(dcc->ssl_ctx, dcc->sock); if (session->verify_callback != NULL) SSL_set_verify(dcc->ssl_ctx, SSL_VERIFY_PEER, session->verify_callback); else SSL_set_verify(dcc->ssl_ctx, SSL_VERIFY_NONE, NULL); // Since we're connecting on our own, tell openssl about it SSL_set_connect_state(dcc->ssl_ctx); } #endif memset(&dcc->remote_addr, 0, sizeof (dcc->remote_addr)); dcc->remote_addr.sin_family = AF_INET; dcc->remote_addr.sin_addr.s_addr = htonl(ip); // what idiot came up with idea to send IP address in host-byteorder? dcc->remote_addr.sin_port = htons(port); dcc->state = LIBIRC_STATE_INIT; dcc->ctx = ctx; time(&dcc->timeout); // and store it libirc_mutex_lock(&session->mutex_dcc); dcc->id = session->dcc_last_id++; dcc->next = session->dcc_sessions; session->dcc_sessions = dcc; libirc_mutex_unlock(&session->mutex_dcc); *pdcc = dcc; return 0; cleanup_exit_error: if (dcc->sock >= 0) socket_close(&dcc->sock); free(dcc); return LIBIRC_ERR_SOCKET; }