int main(int argc, char *argv[]) { if (argc < 4) { helpAndLeave(argv[0], EXIT_FAILURE); } long pid, signal, data, num_sigs; int i; union sigval sv; num_sigs = 1; pid = extract_long(argv[1], "PID"); signal = extract_long(argv[2], "signal"); data = extract_long(argv[3], "data argument"); if (argc > 4) { num_sigs = extract_long(argv[4], "num-signals argument"); } /* Display process PID and UID for help debugging of the receiver */ printf("%s: PID: %ld, UID %ld\n", argv[0], (long) getpid(), (long) getuid()); for (i = 0; i < num_sigs; ++i) { sv.sival_int = data + i; if (sigqueue(pid, signal, sv) == -1) { pexit("sigqueue"); } } exit(EXIT_SUCCESS); }
//-------------------------------------------------------------------------- ssize_t idaapi rpc_debmod_t::dbg_read_file(int fn, uint32 off, void *buf, size_t size) { bytevec_t req = prepare_rpc_packet(RPC_READ_FILE); append_dd(req, fn); append_dd(req, off); append_dd(req, (uint32)size); rpc_packet_t *rp = process_request(req); if ( rp == NULL ) return -1; const uchar *answer = (uchar *)(rp+1); const uchar *end = answer + rp->length; int32 rsize = extract_long(&answer, end); if ( size != rsize ) qerrcode(extract_long(&answer, end)); if ( rsize > 0 ) { if ( rsize > size ) error("rpc_read_file: protocol error"); extract_memory(&answer, end, buf, rsize); } qfree(rp); return rsize; }
//-------------------------------------------------------------------------- int idaapi rpc_debmod_t::dbg_open_file(const char *file, uint32 *fsize, bool readonly) { bytevec_t req = prepare_rpc_packet(RPC_OPEN_FILE); append_str(req, file); append_dd(req, readonly); rpc_packet_t *rp = process_request(req); if ( rp == NULL ) return -1; const uchar *answer = (uchar *)(rp+1); const uchar *end = answer + rp->length; int fn = extract_long(&answer, end); if ( fn != -1 ) { if ( fsize != NULL && readonly ) *fsize = extract_long(&answer, end); } else { qerrcode(extract_long(&answer, end)); } qfree(rp); return fn; }
//-------------------------------------------------------------------------- gdecode_t rpc_debmod_t::dbg_get_debug_event(debug_event_t *event, int timeout_ms) { if ( has_pending_event ) { verbev(("get_debug_event => has pending event, returning it\n")); *event = pending_event; has_pending_event = false; poll_debug_events = false; return GDE_ONE_EVENT; } gdecode_t result = GDE_NO_EVENT; if ( poll_debug_events ) { // do we have something waiting? // we must use TIMEOUT here to avoid competition between // IDA analyzer and the debugger program. // The analysis will be slow during the application run. // As soon as the program is suspended, the analysis will be fast // because get_debug_event() will not be called. if ( irs_ready(irs, TIMEOUT) != 0 ) { verbev(("get_debug_event => remote has an event for us\n")); // get the packet - it should be RPC_EVENT (nothing else can be) qstring empty; int flags = timeout_ms > 0 ? SET_PRF_TIMEOUT(timeout_ms) | PRF_POLL : PRF_DONT_POLL; rpc_packet_t *rp = process_request(empty, flags); verbev(("get_debug_event => processed remote event, has=%d\n", has_pending_event)); if ( rp != NULL || !has_pending_event ) { warning("rpc: event protocol error (rp=%p has_event=%d)", rp, has_pending_event); return GDE_ERROR; } } } else { verbev(("get_debug_event => first time, send GET_DEBUG_EVENT\n")); qstring cmd = prepare_rpc_packet(RPC_GET_DEBUG_EVENT); append_long(cmd, timeout_ms); rpc_packet_t *rp = process_request(cmd); if ( rp == NULL ) return GDE_ERROR; const uchar *answer = (uchar *)(rp+1); const uchar *end = answer + rp->length; result = gdecode_t(extract_long(&answer, end)); if ( result >= GDE_ONE_EVENT ) extract_debug_event(&answer, end, event); else poll_debug_events = true; verbev(("get_debug_event => remote said %d, poll=%d now\n", result, poll_debug_events)); qfree(rp); } return result; }
/* * Administrative Set User Parameters */ void cmd_asup(char *cmdbuf) { struct ctdluser usbuf; char requested_user[128]; char notify[SIZ]; int np; int newax; int deleted = 0; if (CtdlAccessCheck(ac_aide)) return; extract_token(requested_user, cmdbuf, 0, '|', sizeof requested_user); if (CtdlGetUserLock(&usbuf, requested_user) != 0) { cprintf("%d No such user.\n", ERROR + NO_SUCH_USER); return; } np = num_parms(cmdbuf); if (np > 1) extract_token(usbuf.password, cmdbuf, 1, '|', sizeof usbuf.password); if (np > 2) usbuf.flags = extract_int(cmdbuf, 2); if (np > 3) usbuf.timescalled = extract_int(cmdbuf, 3); if (np > 4) usbuf.posted = extract_int(cmdbuf, 4); if (np > 5) { newax = extract_int(cmdbuf, 5); if ((newax >= AxDeleted) && (newax <= AxAideU)) { usbuf.axlevel = newax; } } if (np > 7) { usbuf.lastcall = extract_long(cmdbuf, 7); } if (np > 8) { usbuf.USuserpurge = extract_int(cmdbuf, 8); } CtdlPutUserLock(&usbuf); if (usbuf.axlevel == AxDeleted) { if (purge_user(requested_user) == 0) { deleted = 1; } } if (deleted) { snprintf(notify, SIZ, "User \"%s\" has been deleted by %s.\n", usbuf.fullname, (CC->logged_in ? CC->user.fullname : "an administrator") ); CtdlAideMessage(notify, "User Deletion Message"); } cprintf("%d Ok", CIT_OK); if (deleted) cprintf(" (%s deleted)", requested_user); cprintf("\n"); }
//-------------------------------------------------------------------------- int idaapi rpc_debmod_t::dbg_get_memory_info(meminfo_vec_t &areas) { bytevec_t req = prepare_rpc_packet(RPC_GET_MEMORY_INFO); rpc_packet_t *rp = process_request(req); if ( rp == NULL ) return -1; const uchar *answer = (uchar *)(rp+1); const uchar *end = answer + rp->length; int result = extract_long(&answer, end) - 2; if ( result > 0 ) { int n = extract_long(&answer, end); areas.resize(n); for ( int i=0; i < n; i++ ) extract_memory_info(&answer, end, &areas[i]); } qfree(rp); return result; }
//-------------------------------------------------------------------------- ssize_t idaapi rpc_debmod_t::dbg_write_file(int fn, uint32 off, const void *buf, size_t size) { bytevec_t req = prepare_rpc_packet(RPC_WRITE_FILE); append_dd(req, fn); append_dd(req, off); append_dd(req, (uint32)size); append_memory(req, buf, size); rpc_packet_t *rp = process_request(req); if ( rp == NULL ) return -1; const uchar *answer = (uchar *)(rp+1); const uchar *end = answer + rp->length; int32 rsize = extract_long(&answer, end); if ( size != rsize ) qerrcode(extract_long(&answer, end)); qfree(rp); return rsize; }
//-------------------------------------------------------------------------- gdecode_t idaapi rpc_debmod_t::dbg_get_debug_event(debug_event_t *event, int timeout_ms) { if ( has_pending_event ) { verbev(("get_debug_event => has pending event, returning it\n")); *event = pending_event; has_pending_event = false; poll_debug_events = false; return GDE_ONE_EVENT; } gdecode_t result = GDE_NO_EVENT; if ( poll_debug_events ) { // do we have something waiting? if ( irs_ready(irs, timeout_ms) != 0 ) { verbev(("get_debug_event => remote has an event for us\n")); // get the packet - it should be RPC_EVENT (nothing else can be) bytevec_t empty; rpc_packet_t *rp = process_request(empty); verbev(("get_debug_event => processed remote event, has=%d\n", has_pending_event)); if ( rp != NULL || !has_pending_event ) { warning("rpc: event protocol error (rp=%p has_event=%d)", rp, has_pending_event); return GDE_ERROR; } } } else { verbev(("get_debug_event => first time, send GET_DEBUG_EVENT\n")); bytevec_t req = prepare_rpc_packet(RPC_GET_DEBUG_EVENT); append_dd(req, timeout_ms); rpc_packet_t *rp = process_request(req); if ( rp == NULL ) return GDE_ERROR; const uchar *answer = (uchar *)(rp+1); const uchar *end = answer + rp->length; result = gdecode_t(extract_long(&answer, end)); if ( result >= GDE_ONE_EVENT ) extract_debug_event(&answer, end, event); else poll_debug_events = true; verbev(("get_debug_event => remote said %d, poll=%d now\n", result, poll_debug_events)); qfree(rp); } return result; }
/* * Display a specific page from a wiki room * * "rev" may be set to an empty string to display the current version. * "do_revert" may be set to nonzero to perform a reversion to the specified version. */ void display_wiki_page_backend(char *pagename, char *rev, int do_revert) { wcsession *WCC = WC; const StrBuf *Mime; long msgnum = (-1L); char buf[256]; if ((WCC->CurRoom.view != VIEW_WIKI) && (WCC->CurRoom.view != VIEW_WIKIMD)) { wc_printf(_("'%s' is not a Wiki room."), ChrPtr(WCC->CurRoom.name) ); return; } if (IsEmptyStr(pagename)) { strcpy(pagename, "home"); } str_wiki_index(pagename); /* convert index name to lowercase and numeric only */ if ((rev != NULL) && (strlen(rev) > 0)) { /* read an older revision */ serv_printf("WIKI rev|%s|%s|%s", pagename, rev, (do_revert ? "revert" : "fetch") ); serv_getln(buf, sizeof buf); if (buf[0] == '2') { msgnum = extract_long(&buf[4], 0); } } else { /* read the current revision */ msgnum = locate_message_by_uid(pagename); } if (msgnum >= 0L) { read_message(WCC->WBuf, HKEY("view_message"), msgnum, NULL, &Mime); return; } wc_printf("<br><br>" "<div align=\"center\">" "<table border=\"0\" bgcolor=\"#ffffff\" cellpadding=\"10\">" "<tr><td align=\"center\">" ); wc_printf("<br><b>"); wc_printf(_("There is no page called '%s' here."), pagename); wc_printf("</b><br><br>"); wc_printf(_("Select the 'Edit this page' link in the room banner " "if you would like to create this page.")); wc_printf("<br><br>"); wc_printf("</td></tr></table></div>\n"); }
static long *extract_lonarr(const struct cfg_field *self, size_t *size, enum cfg_status *status) { long *out=NULL, tmp=0; struct cfg_strvec *vec=NULL; size_t i=0; *size=0; *status = CFG_SUCCESS; if (!self) { // not OK to have null field! *status = CFG_EMPTY; goto _extract_lonarr_bail; } vec = CFG_FIELD_GET_VEC(self); if (!vec || vec->size==0) { // ok to have empty array, just exit goto _extract_lonarr_bail; } out = calloc(vec->size, sizeof(long)); if (!out){ fprintf(stderr,"Failed to allocate long array copy for field '%s'\n", CFG_FIELD_NAME(self)); exit(1); } for (i=0; i<vec->size; i++) { tmp = extract_long(vec->data[i], status); if (*status) { goto _extract_lonarr_bail; } out[i] = tmp; } *size = vec->size; _extract_lonarr_bail: if (*status) { free(out); out=NULL; } return out; }
//------------------------------------------------------------------------- int rpc_debmod_t::process_start_or_attach(bytevec_t &req) { rpc_packet_t *rp = process_request(req); if ( rp == NULL ) return -1; const uchar *answer = (uchar *)(rp+1); const uchar *end = answer + rp->length; int result = extract_long(&answer, end); if ( result > 0 ) extract_debapp_attrs(&answer, end, &debapp_attrs); qfree(rp); return result; }
//-------------------------------------------------------------------------- int rpc_debmod_t::dbg_thread_read_registers(thid_t tid, regval_t *values, int n) { qstring cmd = prepare_rpc_packet(RPC_READ_REGS); append_long(cmd, tid); append_long(cmd, n); rpc_packet_t *rp = process_request(cmd); if ( rp == NULL ) return -1; const uchar *answer = (uchar *)(rp+1); const uchar *end = answer + rp->length; int result = extract_long(&answer, end); extract_regvals(&answer, end, values, n); qfree(rp); return result; }
//-------------------------------------------------------------------------- bool idaapi rpc_debmod_t::dbg_update_call_stack(thid_t tid, call_stack_t *trace) { bytevec_t req = prepare_rpc_packet(RPC_UPDATE_CALL_STACK); append_dd(req, tid); rpc_packet_t *rp = process_request(req); if ( rp == NULL ) return false; const uchar *answer = (uchar *)(rp+1); const uchar *end = answer + rp->length; bool result = extract_long(&answer, end) != 0; if ( result ) extract_call_stack(&answer, end, trace); qfree(rp); return result; }
//-------------------------------------------------------------------------- ssize_t rpc_debmod_t::dbg_read_memory(ea_t ea, void *buffer, size_t size) { qstring cmd = prepare_rpc_packet(RPC_READ_MEMORY); append_ea(cmd, ea); append_long(cmd, (uint32)size); rpc_packet_t *rp = process_request(cmd); if ( rp == NULL ) return -1; const uchar *answer = (uchar *)(rp+1); const uchar *end = answer + rp->length; int result = extract_long(&answer, end); extract_memory(&answer, end, buffer, size); qfree(rp); return result; }
//-------------------------------------------------------------------------- // input is valid only if n==0 int rpc_debmod_t::dbg_process_get_info(int n, const char *input, process_info_t *info) { qstring cmd = prepare_rpc_packet(RPC_GET_PROCESS_INFO); append_long(cmd, n); if ( n == 0 ) append_str(cmd, input); rpc_packet_t *rp = process_request(cmd); if ( rp == NULL ) return -1; const uchar *answer = (uchar *)(rp+1); const uchar *end = answer + rp->length; bool result = extract_long(&answer, end); if ( result ) extract_process_info(&answer, end, info); qfree(rp); return result; }
//-------------------------------------------------------------------------- ssize_t idaapi rpc_debmod_t::dbg_read_memory(ea_t ea, void *buffer, size_t size) { bytevec_t req = prepare_rpc_packet(RPC_READ_MEMORY); append_ea64(req, ea); append_dd(req, (uint32)size); rpc_packet_t *rp = process_request(req); if ( rp == NULL ) return -1; const uchar *answer = (uchar *)(rp+1); const uchar *end = answer + rp->length; int result = extract_long(&answer, end); if ( result > 0 ) extract_memory(&answer, end, buffer, result); qfree(rp); return result; }
/* * Public * * Extract a scalar as a long */ long cfg_get_long(const struct cfg *self, const char *name, enum cfg_status *status) { long val=0; const struct cfg_field *field=NULL; char *str=NULL; field = cfg_find(self, name, status); if (*status==CFG_SUCCESS) { if (CFG_TYPE_SCALAR != CFG_FIELD_TYPE(field)) { *status = CFG_TYPE_ERROR; } else { str = CFG_FIELD_GET_DATA(field, 0); val = extract_long(str, status); } } return val; }
void cmd_seen(char *argbuf) { long target_msgnum = 0L; int target_setting = 0; if (CtdlAccessCheck(ac_logged_in)) { return; } if (num_parms(argbuf) != 2) { cprintf("%d Invalid parameters\n", ERROR + ILLEGAL_VALUE); return; } target_msgnum = extract_long(argbuf, 0); target_setting = extract_int(argbuf, 1); CtdlSetSeen(&target_msgnum, 1, target_setting, ctdlsetseen_seen, NULL, NULL); cprintf("%d OK\n", CIT_OK); }
//-------------------------------------------------------------------------- // input is valid only if n==0 int idaapi rpc_debmod_t::dbg_process_get_info(int n, const char *input, process_info_t *procinf) { bytevec_t req = prepare_rpc_packet(RPC_GET_PROCESS_INFO); append_dd(req, n); if ( n == 0 ) append_str(req, input); rpc_packet_t *rp = process_request(req); if ( rp == NULL ) return -1; const uchar *answer = (uchar *)(rp+1); const uchar *end = answer + rp->length; bool result = extract_long(&answer, end) != 0; if ( result ) extract_process_info(&answer, end, procinf); qfree(rp); return result; }
//-------------------------------------------------------------------------- int idaapi rpc_debmod_t::dbg_thread_get_sreg_base(thid_t tid, int sreg_value, ea_t *ea) { bytevec_t req = prepare_rpc_packet(RPC_GET_SREG_BASE); append_dd(req, tid); append_dd(req, sreg_value); rpc_packet_t *rp = process_request(req); if ( rp == NULL ) return -1; const uchar *answer = (uchar *)(rp+1); const uchar *end = answer + rp->length; bool result = extract_long(&answer, end) != 0; if ( result ) *ea = extract_ea64(&answer, end); qfree(rp); return result; }
/* Handle a GGA (GPS data) message. */ static void handle_gga(uint8_t *buf, uint8_t size){ int64_t latitude, longitude; int32_t altitude; uint8_t ftable[15]; if(14 != parse_table(buf, size, ftable, 15))return; if(extract_lat(buf + ftable[2], &latitude))return; if(*(buf + ftable[3]) != 'N' && *(buf + ftable[3]) != 'S')return; if(*(buf + ftable[3]) == 'S')latitude = -latitude; if(extract_long(buf + ftable[4], &longitude))return; if(*(buf + ftable[5]) != 'W' && *(buf + ftable[5]) != 'E')return; if(*(buf + ftable[5]) == 'W')longitude = -longitude; if(*(buf + ftable[6]) == '0')return; /* No fix. */ if(extract_decimal_precision(buf + ftable[9], 1, &altitude))return; Data->latitude = latitude; Data->longitude = longitude; Data->altitude = altitude; Data->gps_pos_valid = 1; start_gps_valid_timer(); }
//-------------------------------------------------------------------------- int rpc_debmod_t::dbg_read_registers(thid_t tid, int clsmask, regval_t *values) { qstring cmd = prepare_rpc_packet(RPC_READ_REGS); append_long(cmd, tid); append_long(cmd, clsmask); // append additional information about the class structure bytevec_t regmap; int nregs = calc_regmap(®map, clsmask); append_long(cmd, nregs); append_memory(cmd, regmap.begin(), regmap.size()); rpc_packet_t *rp = process_request(cmd); if ( rp == NULL ) return -1; const uchar *answer = (uchar *)(rp+1); const uchar *end = answer + rp->length; int result = extract_long(&answer, end); if ( result ) extract_regvals(&answer, end, values, nregs, regmap.begin()); qfree(rp); return result; }
/* * Display the revision history for a wiki page (template callback) */ void tmplput_display_wiki_history(StrBuf *Target, WCTemplputParams *TP) { char pagename[128]; StrBuf *Buf; int row = 0; safestrncpy(pagename, bstr("page"), sizeof pagename); str_wiki_index(pagename); serv_printf("WIKI history|%s", pagename); Buf = NewStrBuf(); StrBuf_ServGetln(Buf); if (GetServerStatus(Buf, NULL) == 1) { time_t rev_date; char rev_date_displayed[64]; StrBuf *rev_uuid = NewStrBuf(); StrBuf *author = NewStrBuf(); StrBuf *node = NewStrBuf(); wc_printf("<table class=\"wiki_history_background\">"); wc_printf("<th>%s</th>", _("Date")); wc_printf("<th>%s</th>", _("Author")); while((StrBuf_ServGetln(Buf) >= 0) && strcmp(ChrPtr(Buf), "000")) { rev_date = extract_long(ChrPtr(Buf), 1); webcit_fmt_date(rev_date_displayed, sizeof rev_date_displayed, rev_date, DATEFMT_FULL); StrBufExtract_token(author, Buf, 2, '|'); wc_printf("<tr bgcolor=\"%s\">", ((row%2) ? "#FFFFFF" : "#DDDDDD")); wc_printf("<td>%s</td><td>", rev_date_displayed); if (!strcasecmp(ChrPtr(node), (char *)WC->serv_info->serv_nodename)) { escputs(ChrPtr(author)); wc_printf(" @ "); escputs(ChrPtr(node)); } else { wc_printf("<a href=\"showuser?who="); urlescputs(ChrPtr(author)); wc_printf("\">"); escputs(ChrPtr(author)); wc_printf("</a>"); } wc_printf("</td>"); if (row == 0) { wc_printf("<td><a href=\"wiki?page=%s", bstr("page")); wc_printf("?go="); urlescputs(ChrPtr(WC->CurRoom.name)); wc_printf("\">%s</a></td>", _("(show)")); wc_printf("<td>(%s)</td>", _("Current version")); } else { wc_printf("<td><a href=\"wiki?page=%s?rev=%s", bstr("page"), ChrPtr(rev_uuid) ); wc_printf("?go="); urlescputs(ChrPtr(WC->CurRoom.name)); wc_printf("\">%s</a></td>", _("(show)")); wc_printf("<td><a href=\"javascript:GetLoggedInFirst(encodeURIComponent('wiki?page=%s?rev=%s?revert=1'))\">%s</a></td>", bstr("page"), ChrPtr(rev_uuid), _("(revert)") ); } wc_printf("</tr>\n"); /* Extract all fields except the author and date after displaying the row. This * is deliberate, because the timestamp reflects when the diff was written, not * when the version which it reflects was written. Similarly, the name associated * with each diff is the author who created the newer version of the page that * made the diff happen. */ StrBufExtract_token(rev_uuid, Buf, 0, '|'); StrBufExtract_token(node, Buf, 3, '|'); ++row; } wc_printf("</table>\n"); FreeStrBuf(&author); FreeStrBuf(&node); FreeStrBuf(&rev_uuid); } else { wc_printf("%s", ChrPtr(Buf)); } FreeStrBuf(&Buf); }
//-------------------------------------------------------------------------- static void handle_single_session(rpc_server_t *server) { lprintf("=========================================================\n" "Accepting incoming connection...\n"); qstring open = prepare_rpc_packet(RPC_OPEN); append_long(open, IDD_INTERFACE_VERSION); append_long(open, DEBUGGER_ID); append_long(open, sizeof(ea_t)); rpc_packet_t *rp = server->process_request(open, PRF_LOGIN|PRF_DONT_POLL); if ( rp == NULL ) { lprintf("Could not establish the connection\n"); delete server; return; } // Answer is beyond the rpc_packet_t buffer const uchar *answer = (uchar *)(rp+1); const uchar *end = answer + rp->length; bool send_response = true; bool ok = extract_long(&answer, end); if ( !ok ) { lprintf("Incompatible IDA Pro version\n"); send_response = false; } else if ( server_password != NULL ) { char *pass = extract_str(&answer, end); if ( strcmp(pass, server_password) != '\0' ) { lprintf("Bad password\n"); ok = false; } } qfree(rp); if ( send_response ) { server->poll_debug_events = false; server->has_pending_event = false; open = prepare_rpc_packet(RPC_OK); append_long(open, ok); server->send_request(open); if ( ok ) { qstring cmd; rpc_packet_t *packet = server->process_request(cmd, PRF_POLL); if ( packet != NULL ) qfree(packet); } } server->network_error_code = 0; lprintf("Closing incoming connection...\n"); server->term_irs(); #ifndef __SINGLE_THREADED_SERVER__ // Remove the session from the list qmutex_lock(g_lock); for (rpc_server_list_t::iterator it = clients_list.begin(); it != clients_list.end();++it) { if ( it->first != server ) continue; // free the thread resources qthread_free(it->second); // remove client from the list clients_list.erase(it); break; } qmutex_unlock(g_lock); #endif // Free the debug session delete server; }
//-------------------------------------------------------------------------- int idaapi rpc_debmod_t::dbg_update_bpts(update_bpt_info_t *ubpts, int nadd, int ndel) { int skipped = 0; update_bpt_info_t *b; update_bpt_info_t *bend = ubpts + nadd; for ( b=ubpts; b != bend; b++ ) if ( b->code != BPT_OK ) skipped++; if ( skipped == nadd && ndel == 0 ) return 0; // no bpts to update bytevec_t req = prepare_rpc_packet(RPC_UPDATE_BPTS); append_dd(req, nadd-skipped); append_dd(req, ndel); ea_t ea = 0; for ( b=ubpts; b != bend; b++ ) { if ( b->code == BPT_OK ) { append_ea64(req, b->ea-ea); ea = b->ea; append_dd(req, b->size); append_dd(req, b->type); } } ea = 0; bend += ndel; for ( ; b != bend; b++ ) { append_ea64(req, b->ea-ea); ea = b->ea; append_db(req, b->orgbytes.size()); append_memory(req, b->orgbytes.begin(), b->orgbytes.size()); append_dd(req, b->type); } rpc_packet_t *rp = process_request(req); if ( rp == NULL ) return -1; const uchar *ptr = (uchar *)(rp+1); const uchar *end = ptr + rp->length; int ret = extract_long(&ptr, end); bend = ubpts + nadd; for ( b=ubpts; b != bend; b++ ) { if ( b->code == BPT_OK ) { b->code = extract_byte(&ptr, end); if ( b->code == BPT_OK && b->type == BPT_SOFT ) { uchar len = extract_byte(&ptr, end); b->orgbytes.resize(len); extract_memory(&ptr, end, b->orgbytes.begin(), len); } } } bend += ndel; for ( ; b != bend; b++ ) b->code = extract_byte(&ptr, end); return ret; }
//-------------------------------------------------------------------------- bool rpc_debmod_t::open_remote( const char *hostname, int port_number, const char *password) { rpc_packet_t *rp = NULL; network_error_code = 0; irs = init_client_irs(hostname, port_number); if ( irs == NULL ) { FAILURE: if ( rp != NULL ) qfree(rp); term_irs(); return false; } rp = recv_request(); if ( rp == NULL || rp->code != RPC_OPEN ) // is this an ida debugger server? { rpc_client_t::dwarning("ICON ERROR\nAUTOHIDE NONE\n" "Bogus or irresponsive remote server"); goto FAILURE; } const uchar *answer = (uchar *)(rp+1); const uchar *end = answer + rp->length; int version = extract_long(&answer, end); int remote_debugger_id = extract_long(&answer, end); int easize = extract_long(&answer, end); qstring errstr; if ( version != IDD_INTERFACE_VERSION ) errstr.sprnt("protocol version is %d, expected %d", version, IDD_INTERFACE_VERSION); else if ( remote_debugger_id != debugger.id ) errstr.sprnt("debugger id is %d, expected %d (%s)", remote_debugger_id, debugger.id, debugger.name); else if ( easize != get_expected_addrsize() ) errstr.sprnt("address size is %d bytes, expected %d", easize, inf.is_64bit() ? 8 : 4); if ( !errstr.empty() ) { bytevec_t req = prepare_rpc_packet(RPC_OK); append_dd(req, false); send_request(req); warning("ICON ERROR\nAUTOHIDE NONE\n" "Incompatible debugging server:\n" "%s\n", errstr.c_str()); goto FAILURE; } qfree(rp); bytevec_t req = prepare_rpc_packet(RPC_OK); append_dd(req, true); append_str(req, password); send_request(req); rp = recv_request(); if ( rp == NULL || rp->code != RPC_OK ) goto FAILURE; answer = (uchar *)(rp+1); end = answer + rp->length; bool password_ok = extract_long(&answer, end) != 0; if ( !password_ok ) // is this an ida debugger server? { warning("ICON ERROR\nAUTOHIDE NONE\n" "Bad password"); goto FAILURE; } qfree(rp); return true; }
//-------------------------------------------------------------------------- // requests received from the server. // here the client handles certain server -> client requests qstring rpc_client_t::perform_request(const rpc_packet_t *rp) { const uchar *ptr = (const uchar *)(rp + 1); const uchar *end = ptr + rp->length; qstring cmd = prepare_rpc_packet(RPC_OK); switch ( rp->code ) { case RPC_SET_DEBUG_NAMES: { int qty = extract_long(&ptr, end); ea_t *addrs = new ea_t[qty]; if ( addrs == NULL ) goto nomem; char **names = new char *[qty]; if ( names == NULL ) { delete [] addrs; goto nomem; } char name[MAXSTR]; ea_t old = 0; name[0] = '\0'; for ( int i=0; i < qty; i++ ) { adiff_t o2 = extract_ea(&ptr, end); if ( extract_long(&ptr, end) ) o2 = -o2; old += o2; addrs[i] = old; int oldlen = extract_long(&ptr, end); qstrncpy(&name[oldlen], extract_str(&ptr, end), sizeof(name)-oldlen); names[i] = qstrdup(name); } int result = set_debug_names(addrs, names, qty); verb(("set_debug_name(qty=%d) => %d\n", qty, result)); append_long(cmd, result); for ( int i=0; i < qty; i++ ) qfree(names[i]); delete [] addrs; delete [] names; } break; case RPC_HANDLE_DEBUG_EVENT: { debug_event_t ev; extract_debug_event(&ptr, end, &ev); int rqflags = extract_long(&ptr, end); int code = send_debug_event_to_ida(&ev, rqflags); append_long(cmd, code); } break; case RPC_SYNC_STUB: { char *fname = extract_str(&ptr, end); uint32 crc = extract_long(&ptr, end); size_t size = 0; uchar *contents = sync_stub(fname, crc, &size); append_long(cmd, (uint32)size); if ( contents != NULL ) { append_memory(cmd, contents, size); qfree(contents); } } break; case RPC_ERROR: case RPC_MSG: case RPC_WARNING: { char *str = extract_str(&ptr, end); if ( rp->code == RPC_MSG) msg("%s", str); else if ( rp->code == RPC_ERROR ) error("%s", str); else warning("%s", str); } break; case RPC_EVENT: { extract_debug_event(&ptr, end, &pending_event); has_pending_event = true; cmd = prepare_rpc_packet(RPC_EVOK); verbev(("got event, storing it and sending RPC_EVOK\n")); } break; case RPC_IOCTL: { int code = handle_ioctl_packet(cmd, ptr, end); if ( code != RPC_OK ) return prepare_rpc_packet((uchar)code); } break; default: return prepare_rpc_packet(RPC_UNK); nomem: return prepare_rpc_packet(RPC_MEM); } return cmd; }
int main(int argc, char *argv[]) { int a, i; int curr; char buf[1024]; char aaa[128]; int relh = 0; int home = 0; int nRetries = 0; char relhome[PATH_MAX]=""; char ctdldir[PATH_MAX]=CTDLDIR; struct passwd *pw; gid_t gid; char *activity = NULL; /* Keep a mild groove on */ program_title = _("Citadel setup program"); /* set an invalid setup type */ setup_type = (-1); /* parse command line args */ for (a = 0; a < argc; ++a) { if (!strncmp(argv[a], "-u", 2)) { strcpy(aaa, argv[a]); strcpy(aaa, &aaa[2]); setup_type = atoi(aaa); } else if (!strcmp(argv[a], "-q")) { setup_type = UI_SILENT; } else if (!strncmp(argv[a], "-h", 2)) { relh=argv[a][2]!='/'; if (!relh) { safestrncpy(ctdl_home_directory, &argv[a][2], sizeof ctdl_home_directory); } else { safestrncpy(relhome, &argv[a][2], sizeof relhome); } home = 1; } } calc_dirs_n_files(relh, home, relhome, ctdldir, 0); SetTitles(); /* If a setup type was not specified, try to determine automatically * the best one to use out of all available types. */ if (setup_type < 0) { setup_type = discover_ui(); } enable_home = ( relh | home ); if (chdir(ctdl_run_dir) != 0) { display_error("%s: [%s]\n", _("The directory you specified does not exist"), ctdl_run_dir); exit(errno); } /* * Connect to the running Citadel server. */ while ((serv_sock < 0) && (nRetries < 10)) { serv_sock = uds_connectsock(file_citadel_admin_socket); nRetries ++; if (serv_sock < 0) sleep(1); } if (serv_sock < 0) { display_error( "%s: %s %s\n", _("Setup could not connect to a running Citadel server."), strerror(errno), file_citadel_admin_socket ); exit(1); } /* * read the server greeting */ serv_gets(buf); if (buf[0] != '2') { display_error("%s\n", buf); exit(2); } /* * Are we connected to the correct Citadel server? */ serv_puts("INFO"); serv_gets(buf); if (buf[0] != '1') { display_error("%s\n", buf); exit(3); } a = 0; while (serv_gets(buf), strcmp(buf, "000")) { if (a == 5) { if (atoi(buf) != REV_LEVEL) { display_error("%s\n", _("Your setup program and Citadel server are from different versions.") ); exit(4); } } ++a; } /* * Now begin. */ if (setup_type == UI_TEXT) { printf("\n\n\n *** %s ***\n\n", program_title); } if (setup_type == UI_DIALOG) { system("clear 2>/dev/null"); } /* Go through a series of dialogs prompting for config info */ for (curr = 1; curr < eMaxQuestions; ++curr) { edit_value(curr); if ( (curr == eAuthType) && (getconf_int("c_auth_mode") != AUTHMODE_LDAP) && (getconf_int("c_auth_mode") != AUTHMODE_LDAP_AD) ) { curr += 5; /* skip LDAP questions if we're not authenticating against LDAP */ } if (curr == eSysAdminName) { if (getconf_int("c_auth_mode") == AUTHMODE_NATIVE) { /* for native auth mode, fetch the admin's existing pw */ snprintf(buf, sizeof buf, "AGUP %s", admin_name); serv_puts(buf); serv_gets(buf); if (buf[0] == '2') { extract_token(admin_pass, &buf[4], 1, '|', sizeof admin_pass); } } else { ++curr; /* skip the password question for non-native auth modes */ } } } if ((pw = getpwuid( getconf_int("c_ctdluid") )) == NULL) { gid = getgid(); } else { gid = pw->pw_gid; } if (create_run_directories(getconf_int("c_ctdluid"), gid) != 0) { display_error("%s\n", _("failed to create directories")); } activity = _("Reconfiguring Citadel server"); progress(activity, 0, 5); sleep(1); /* Let the message appear briefly */ /* * Create the administrator account. It's ok if the command fails if this user already exists. */ progress(activity, 1, 5); snprintf(buf, sizeof buf, "CREU %s|%s", admin_name, admin_pass); serv_puts(buf); progress(activity, 2, 5); serv_gets(buf); progress(activity, 3, 5); /* * Assign the desired password and access level to the administrator account. */ snprintf(buf, sizeof buf, "AGUP %s", admin_name); serv_puts(buf); progress(activity, 4, 5); serv_gets(buf); if (buf[0] == '2') { int admin_flags = extract_int(&buf[4], 2); int admin_times_called = extract_int(&buf[4], 3); int admin_msgs_posted = extract_int(&buf[4], 4); snprintf(buf, sizeof buf, "ASUP %s|%s|%d|%d|%d|6", admin_name, admin_pass, admin_flags, admin_times_called, admin_msgs_posted ); serv_puts(buf); serv_gets(buf); } progress(activity, 5, 5); #ifndef __CYGWIN__ check_xinetd_entry(); /* Check /etc/xinetd.d/telnet */ disable_other_mtas(); /* Offer to disable other MTAs */ fixnss(); /* Check for the 'db' nss and offer to disable it */ #endif /* * Restart citserver */ activity = _("Restarting Citadel server to apply changes"); progress(activity, 0, 41); serv_puts("TIME"); serv_gets(buf); long original_start_time = extract_long(&buf[4], 3); progress(activity, 1, 41); serv_puts("DOWN 1"); progress(activity, 2, 41); serv_gets(buf); if (buf[0] != '2') { display_error("%s\n", buf); exit(6); } close(serv_sock); serv_sock = (-1); for (i=3; i<=6; ++i) { /* wait for server to shut down */ progress(activity, i, 41); sleep(1); } for (i=7; ((i<=38) && (serv_sock < 0)) ; ++i) { /* wait for server to start up */ progress(activity, i, 41); serv_sock = uds_connectsock(file_citadel_admin_socket); sleep(1); } progress(activity, 39, 41); serv_gets(buf); progress(activity, 40, 41); serv_puts("TIME"); serv_gets(buf); long new_start_time = extract_long(&buf[4], 3); close(serv_sock); progress(activity, 41, 41); if ( (original_start_time == new_start_time) || (new_start_time <= 0) ) { display_error("%s\n", _("Setup failed to restart Citadel server. Please restart it manually.")); exit(7); } exit(0); return 0; }
//---------------------------------------------------------- main thread --- int idaapi win32_debmod_t::handle_ioctl( int fn, const void *buf, size_t size, void **poutbuf, ssize_t *poutsize) { qnotused(size); switch ( fn ) { case WIN32_IOCTL_RDMSR: QASSERT(30119, size == sizeof(uval_t)); { uint64 value; uval_t reg = *(uval_t *)buf; int code = rdmsr(reg, &value); if ( SUCCEEDED(code) ) { *poutbuf = qalloc(sizeof(value)); if ( *poutbuf != NULL ) { memcpy(*poutbuf, &value, sizeof(value)); *poutsize = sizeof(value); } } return code; } case WIN32_IOCTL_WRMSR: QASSERT(30120, size == sizeof(win32_wrmsr_t)); { win32_wrmsr_t &msr = *(win32_wrmsr_t *)buf; return wrmsr(msr.reg, msr.value); } #ifdef ENABLE_REMOTEPDB case WIN32_IOCTL_STARTPDB: QASSERT(30192, size >= sizeof(uint64)); { qstring errmsg; if ( pdbthread.is_running() ) { errmsg = "Only one PDB conversion at a time is supported!"; PDBERROR: *poutsize = errmsg.size(); *poutbuf = errmsg.extract(); return -2; } const uchar *ptr = (const uchar *)buf; const uchar *end = ptr + size; compiler_info_t cc; extract_memory(&ptr, end, &cc, sizeof(cc)); ea_t base_ea = extract_ea64(&ptr, end); const char *pdbfile = extract_str(&ptr, end); const char *dpath = extract_str(&ptr, end); const char *spath = extract_str(&ptr, end); if ( !pdbthread.do_convert(cc, base_ea, pdbfile, dpath, spath) ) { errmsg = "Error starting PDB conversion!"; goto PDBERROR; } return 0x1234; // dummy ID } case WIN32_IOCTL_DONEPDB: { qstring errmsg; if ( !pdbthread.is_running() ) { errmsg = "PDB conversion is not started!"; PDBERROR2: *poutsize = errmsg.size(); *poutbuf = errmsg.extract(); return -2; } const uchar *ptr = (const uchar *)buf; const uchar *end = ptr + size; uint32 id = extract_long(&ptr, end); if ( id != 0x1234 ) { errmsg = "Bad conversion ID"; goto PDBERROR2; } if ( pdbthread.is_waiting_req() ) { // we've got a read request, handle it now handle_pdb_request(); pdbthread.post_req_done(); } if ( pdbthread.is_done() ) { // done pdbthread.finalize(); *poutsize = pdbthread.tilfname.size(); *poutbuf = pdbthread.tilfname.extract(); return 2; } else { // not done yet return 1; } } case WIN32_IOCTL_RMFILE: { qstring errmsg; const uchar *ptr = (const uchar *)buf; const uchar *end = ptr + size; const char *filename = extract_str(&ptr, end); if ( filename == NULL ) { errmsg = "Filename missing"; PDBERROR3: *poutsize = errmsg.size(); *poutbuf = errmsg.extract(); return -2; } if ( unlink(filename) != 0 ) { errmsg = "Error deleting file"; goto PDBERROR3; } return 1; } #endif // REMOTEPDB default: break; } return 0; }
//-------------------------------------------------------------------------- bool rpc_debmod_t::open_remote(const char *hostname, int port_number, const char *password) { rpc_packet_t *rp = NULL; irs = init_client_irs(hostname, port_number); if (irs == NULL) { failed: connection_failed(rp); return false; } rp = recv_request(PRF_DONT_POLL); if ( rp == NULL ) goto failed; if ( rp->code != RPC_OPEN ) // is this an ida debugger server? { connection_failed(rp); rpc_client_t::dwarning("ICON ERROR\nAUTOHIDE NONE\n" "Bogus remote server"); return false; } const uchar *answer = (uchar *)(rp+1); const uchar *end = answer + rp->length; int version = extract_long(&answer, end); int remote_debugger_id = extract_long(&answer, end); int easize = extract_long(&answer, end); qstring errstr; if ( version != IDD_INTERFACE_VERSION ) errstr.sprnt("protocol version is %d, expected %d", version, IDD_INTERFACE_VERSION); else if ( remote_debugger_id != debugger.id ) errstr.sprnt("debugger id is %d, expected %d (%s)", remote_debugger_id, debugger.id, debugger.name); else if ( easize != (inf.is_64bit() ? 8 : 4) ) errstr.sprnt("address size is %d bytes, expected %d", easize, inf.is_64bit() ? 8 : 4); if ( !errstr.empty() ) { connection_failed(rp); qstring cmd = prepare_rpc_packet(RPC_OK); append_long(cmd, false); send_request(cmd); warning("ICON ERROR\nAUTOHIDE NONE\n" "Incompatible debugging server:\n" "%s\n", errstr.c_str()); return false; } qfree(rp); qstring cmd = prepare_rpc_packet(RPC_OK); append_long(cmd, true); append_str(cmd, password); send_request(cmd); rp = recv_request(PRF_DONT_POLL); if ( rp == NULL || rp->code != RPC_OK ) goto failed; answer = (uchar *)(rp+1); end = answer + rp->length; bool password_ok = extract_long(&answer, end); if ( !password_ok ) // is this an ida debugger server? { connection_failed(rp); warning("ICON ERROR\nAUTOHIDE NONE\n" "Bad password"); return false; } qfree(rp); return true; }