Stackdb
Stackdb is a stackable, multi-target and -level source debugger and memory forensics library.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
analysis_rpc.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012, 2013, 2014 The University of Utah
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of
7  * the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #include "analysis_xml.h"
20 #include "analysis_rpc.h"
21 
22 #include "log.h"
23 #include "monitor.h"
24 
25 #include "analysis.h"
26 #include "target_api.h"
27 #include "target.h"
28 
29 #include "generic_rpc.h"
30 #include "target_rpc.h"
31 #include "proxyreq.h"
32 #include "util.h"
33 #include "common_xml.h"
34 #include "analysis_xml.h"
35 #include "target_xml.h"
36 
37 #include "analysis_listener_moduleStub.h"
38 
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <signal.h>
42 
43 static pthread_mutex_t analysis_rpc_mutex = PTHREAD_MUTEX_INITIALIZER;
44 static int init_done = 0;
45 
46 extern struct vmi1__DebugFileOptsT defDebugFileOpts;
47 
51 static int analysis_rpc_monitor_evloop_attach(struct evloop *evloop,void *obj);
52 static int analysis_rpc_monitor_evloop_detach(struct evloop *evloop,void *obj);
53 static int analysis_rpc_monitor_close(struct monitor *monitor,
54  void *obj,void *objstate,
55  int kill,int kill_sig);
56 static int analysis_rpc_monitor_fini(struct monitor *monitor,
57  void *obj,void *objstate);
58 static int analysis_rpc_monitor_evloop_is_attached(struct evloop *evloop,
59  void *obj);
60 static int analysis_rpc_monitor_error(monitor_error_t error,void *obj);
61 static int analysis_rpc_monitor_fatal_error(monitor_error_t error,void *obj);
62 static int analysis_rpc_monitor_event(struct monitor *monitor,
63  monitor_event_t event,
64  int objid,void *obj);
65 static int analysis_rpc_monitor_child_recv_msg(struct monitor *monitor,
66  struct monitor_msg *msg);
67 static int analysis_rpc_monitor_recv_msg(struct monitor *monitor,
68  struct monitor_msg *msg);
69 
71  .evloop_attach = NULL,
72  .evloop_detach = NULL,
73  .close = analysis_rpc_monitor_close,
74  .fini = analysis_rpc_monitor_fini,
75  .evloop_is_attached = NULL,
76  .error = analysis_rpc_monitor_error,
77  .fatal_error = analysis_rpc_monitor_fatal_error,
78  .event = analysis_rpc_monitor_event,
79  .child_recv_msg = analysis_rpc_monitor_child_recv_msg,
80  .recv_msg = analysis_rpc_monitor_recv_msg,
81 };
82 
86 void analysis_rpc_init(void) {
87  pthread_mutex_lock(&analysis_rpc_mutex);
88 
89  if (init_done) {
90  pthread_mutex_unlock(&analysis_rpc_mutex);
91  return;
92  }
93 
94  monitor_init();
95  analysis_init();
98 
100 
102  &analysis_rpc_monitor_objtype_ops,
103  &analysis_rpc_mutex);
104 
105  init_done = 1;
106 
107  pthread_mutex_unlock(&analysis_rpc_mutex);
108 }
109 
110 void analysis_rpc_fini(void) {
111  void *objid;
112  struct array_list *alist;
113  int i;
114  struct analysis *a = NULL;
115  struct monitor *m = NULL;
116 
117  pthread_mutex_lock(&analysis_rpc_mutex);
118 
119  if (!init_done) {
120  pthread_mutex_unlock(&analysis_rpc_mutex);
121  return;
122  }
123 
124  pthread_mutex_unlock(&analysis_rpc_mutex);
125 
126  /* Nuke any existing analyses. */
127  alist =
129 
130  array_list_foreach(alist,i,objid) {
131  a = NULL;
132  m = NULL;
133  if (!monitor_lookup_objid((int)(uintptr_t)objid,NULL,(void **)&a,&m)
134  || !a)
135  continue;
136  monitor_del_objid(m,(int)(uintptr_t)objid);
138  (int)(uintptr_t)objid);
139  }
140 
142 
143  target_rpc_fini();
145  analysis_fini();
146  monitor_fini();
147 
148  init_done = 0;
149 
150  pthread_mutex_unlock(&analysis_rpc_mutex);
151 }
152 
159 int analysis_rpc_handle_request(struct soap *soap) {
160  return proxyreq_handle_request(soap,"analysis");
161 }
162 
164  GHashTable *reftab;
165  struct vmi1__AnalysisResultT result;
168 };
169 
170 static int _analysis_rpc_notify_listener_result(struct generic_rpc_listener *l,
171  int is_owner,void *data) {
172  result_t retval;
174  (struct analysis_rpc_listener_result_data *)data;
175  int rc;
176 
177  /*
178  * This stinks... but if we were the first
179  */
180 
181  rc = soap_call_vmi1__AnalysisResultNotification(&l->soap,l->url,NULL,
182  &d->result,&d->r);
183  if (rc != SOAP_OK) {
184  if (l->soap.error == SOAP_EOF && l->soap.errnum == 0) {
185  vwarn("timeout notifying %s; removing!",l->url);
186  }
187  else {
188  verrorc("AnalysisResult client call failure %s : ",
189  l->url);
190  soap_print_fault(&l->soap,stderr);
191  }
192  /* Let generic_rpc do this... */
193  //soap_closesock(&lad->soap);
194  return -1;
195  }
196 
197  retval = x_ResultT_to_t_result_t(&l->soap,d->r.result);
198  if (is_owner) {
199  //if (retval > lad->retval)
200  d->retval = retval;
201 
202  vdebug(5,LA_XML,LF_RPC,
203  "notified authoritative listener %s (which returned %d)\n",
204  l->url,retval);
205  }
206  else {
207  vdebug(5,LA_XML,LF_RPC,
208  "notified non-authoritative listener %s (which returned %d)\n",
209  l->url,retval);
210  }
211 
212  if (!l->soap.keep_alive)
213  soap_closesock(&l->soap);
214  /*
215  * Clean up temp/serialization data, but don't kill the sock if we
216  * can avoid it.
217  */
218  soap_destroy(&l->soap);
219  soap_end(&l->soap);
220  //soap_done(&l->soap);
221 
222  return 0;
223 }
224 
226  struct analysis_datum *datum) {
227  struct soap encoder;
229 
230  memset(&d,0,sizeof(d));
232 
233  /*
234  * We only want to build the gsoap data struct once -- so we have to
235  * set up a temp soap struct to do that on. We can't use the
236  * per-listener soap struct yet cause we don't have it until we're
237  * in the iterator above.
238  */
239  soap_init(&encoder);
240  d.reftab = g_hash_table_new_full(g_direct_hash,g_direct_equal,NULL,NULL);
241 
242  a_analysis_datum_to_x_AnalysisResultT(&encoder,datum,analysis,d.reftab,&d.result);
243 
245  _analysis_rpc_notify_listener_result,&d);
246  /*
247  * Clean up temp/serialization data, but don't kill the sock if we
248  * can avoid it.
249  */
250  g_hash_table_destroy(d.reftab);
251  soap_destroy(&encoder);
252  soap_end(&encoder);
253  soap_done(&encoder);
254 
255  return 0;
256 }
257 
258 #define _CB_SAVEBUF_INC 1024
259 
260 int analysis_rpc_stdout_callback(int fd,char *buf,int len,void *state) {
261  struct analysis *a = (struct analysis *)state;
262  char *name = NULL;
263  int id = -1;
264  int type = -1;
265  char *result_value = NULL;
266  char *value_str = NULL;
267  char *msg = NULL;
268  struct analysis_datum *datum;
269  int rc;
270  char rt = 0;
271  int remaining;
272  char *sbuf;
273  char *ebuf;
274  char *pbuf;
275  char *rbuf;
276  char *pbuf_next;
277  int saved = 0;
278  int new_alen = 0;
279  char *token,*token_end,*token_middle;
280  int ccount;
281  char *key,*key_end;
282 
283  vdebug(5,LA_XML,LF_RPC,"fd %d recv '%s' (%d)\n",fd,buf,len);
284 
285  /*
286  * Don't go to any effort if we don't need to...
287  */
289  return 0;
290 
291  /*
292  * If we're going to try to parse it, make sure we have at least one
293  * RESULT:: and one ::RESULT in our buffer. Once we do, process as many of these tag pairs as are
294  * in the buffer. If there is any stuff left, place it at the head
295  * of the buffer for next time.
296  *
297  * NB: the buf we get is NULL-terminated, but len does not include
298  * the NULL. Convenience. SO -- if we copy the buf, make sure to
299  * always keep the destination NULL-terminated too so we can always
300  * use sscanf safely.
301  */
302  if (a->stdout_buf) {
303  if ((len + 1) <= (a->stdout_buf_alen - a->stdout_buf_len)) {
304  memcpy(a->stdout_buf + a->stdout_buf_len,buf,len);
305  a->stdout_buf_len += len;
306  a->stdout_buf[a->stdout_buf_len] = '\0';
307 
308  vdebug(8,LA_XML,LF_RPC,
309  "appending new input to existing buf; will process '''%s'''\n",
310  a->stdout_buf);
311  }
312  else {
313  new_alen = a->stdout_buf_len + len + 1;
314  if (new_alen % _CB_SAVEBUF_INC > 0)
315  new_alen += new_alen % _CB_SAVEBUF_INC;
316  a->stdout_buf = realloc(a->stdout_buf,new_alen);
317  a->stdout_buf_alen = new_alen;
318  memcpy(a->stdout_buf + a->stdout_buf_len,buf,len);
319  a->stdout_buf_len += len;
320  a->stdout_buf[a->stdout_buf_len] = '\0';
321 
322  vdebug(8,LA_XML,LF_RPC,
323  "enlarged existing buf with new input; will process '''%s'''\n",
324  a->stdout_buf);
325  }
326  sbuf = pbuf = a->stdout_buf;
327  saved = 1;
328  remaining = a->stdout_buf_len;
329  }
330  else {
331  sbuf = pbuf = buf;
332  saved = 0;
333  remaining = len;
334 
335  vdebug(8,LA_XML,LF_RPC,
336  "will process callback buf direct; input is '''%s'''\n",
337  pbuf);
338  }
339  /* One byte past the last char in buf. */
340  ebuf = sbuf + remaining;
341 
342  rbuf = strstr(pbuf,"RESULT::");
343  if (rbuf)
344  pbuf_next = strstr(rbuf + 1,"::RESULT\n");
345  else
346  pbuf_next = NULL;
347 
348  if (!pbuf_next) {
349  /*
350  * No tag pair yet, save it off it we didn't do it already, and
351  * return.
352  */
353  if (!saved) {
354  new_alen = a->stdout_buf_len + len + 1;
355  if (new_alen % _CB_SAVEBUF_INC > 0)
356  new_alen += new_alen % _CB_SAVEBUF_INC;
357  a->stdout_buf = malloc(new_alen);
358  a->stdout_buf_alen = new_alen;
359  memcpy(a->stdout_buf,buf,len);
360  a->stdout_buf_len = len;
361  a->stdout_buf[a->stdout_buf_len] = '\0';
362 
363  vdebug(8,LA_XML,LF_RPC,
364  "no tag pair in direct buf; saved;"
365  " next callback will start with '''%s'''\n",
366  a->stdout_buf);
367  }
368  else {
369  vdebug(8,LA_XML,LF_RPC,
370  "no tag pair in direct buf; already saved;"
371  " next callback will start with '''%s'''\n",
372  a->stdout_buf);
373  }
374  return RESULT_SUCCESS;
375  }
376 
377  /*
378  * Ok, we have at least one line; process until we're done.
379  */
380  *(pbuf_next - 1) = '\0';
381  while (pbuf_next) {
382  rt = 0;
383  msg = value_str = name = result_value = NULL;
384  ccount = 0;
385  rc = sscanf(rbuf,"RESULT:: (%c:%d) %ms (%d) %ms \"%m[^\"]\" %n",
386  &rt,&id,&name,&type,&result_value,&msg,&ccount);
387  if (rc >= 5) {
388  /*
389  * Don't bother to create an intermediate result if there are no
390  * listeners.
391  */
392  if (rt != 'f'
394  if (msg)
395  free(msg);
396  if (name)
397  free(name);
398  if (result_value)
399  free(result_value);
400  goto do_continue;
401  }
402 
403  if (ccount > 0) {
404  value_str = rbuf + ccount;
405  while (*value_str != '\0') {
406  if (*value_str == '(') {
407  ++value_str;
408  break;
409  }
410  ++value_str;
411  }
412  if (*value_str == '\0')
413  value_str = NULL;
414  }
415 
416  datum = analysis_create_simple_datum(a,id,name,type,result_value,
417  msg,1);
418  if (value_str) {
419  vdebug(8,LA_XML,LF_RPC,
420  "trying to autoparse value_str '''%s'''\n",value_str);
421  token = value_str;
422  key = NULL;
423  key_end = NULL;
424 
425  int vo = 0;
426  int vc = 0;
427 
428  while (*token != '\0') {
429  key = token;
430  key_end = index(token,'=');
431  if (!key_end) {
432  fprintf(stderr,
433  "bad autoparse value token at '%s'; skipping!\n",
434  token);
435  break;
436  }
437  *key_end = '\0';
438  token_middle = key_end + 1;
439 
440  int depth = 1;
441  switch (*token_middle) {
442  case '[': vo = '['; vc = ']'; break;
443  case '{': vo = '{'; vc = '}'; break;
444  case '"': vo = '"'; vc = '"'; break;
445  case '\'': vo = '\''; vc = '\''; break;
446  case '(': vo = '('; vc = ')'; break;
447  case '`': vo = '`'; vc = '`'; break;
448  case '<': vo = '<'; vc = '>'; break;
449  case '|': vo = '|'; vc = '|'; break;
450  default: vo = vc = 0; depth = 0; break;
451  }
452 
453  /*
454  * Find the end of the current value -- either by
455  * finding a "vc" char match (and handling
456  * nesting/escaping of the vo/vc chars).
457  *
458  * Then look for ',' or ')' to close the deal.
459  */
460  token_end = token_middle;
461  if (depth > 0)
462  ++token_end;
463  //int depth = 0;
464  int inesc = 0;
465  while (*token_end != '\0') {
466  if (inesc) {
467  inesc = 0;
468  }
469  else if (*token_end == '\\'
470  && vo && vc
471  && (*(token_end+1) == vo || *(token_end+1) == vc)) {
472  inesc = 1;
473  }
474  else {
475  /* Not in escape; count nesting first. */
476  if ((token_end != token_middle)
477  && vc && *token_end == vc) {
478  --depth;
479  if (depth == 0) {
480  /* Done with this value */
481  ++token_end;
482  int oldtoken_end = *token_end;
483  *token_end = '\0';
484  vdebug(8,LA_XML,LF_RPC,
485  "found '%s' = '%s'\n",key,token_middle);
487  token_middle,
488  0);
489  *token_end = oldtoken_end;
490  token_middle = token_end;
491  key = NULL;
492 
493  break;
494  }
495  }
496  else if ((token_end != token_middle)
497  && vo && *token_end == vo)
498  ++depth;
499  else if (!vo && !vc && (*token_end == ','
500  || *token_end == ')')) {
501  /* Done with this value */
502  int oldtoken_end = *token_end;
503  *token_end = '\0';
504  vdebug(8,LA_XML,LF_RPC,
505  "found '%s' = '%s'\n",key,token_middle);
507  token_middle,
508  0);
509  *token_end = oldtoken_end;
510  token_middle = token_end;
511  key = NULL;
512 
513  break;
514  }
515  }
516 
517  ++token_end;
518  }
519 
520  /*
521  * When we get here, we're looking for the next ','
522  * or ')'.
523  */
524  token = index(token_end,',');
525  if (!token)
526  break;
527  else
528  ++token;
529  //token = token_end;
530  }
531 
532  }
533 
537 
538  if (rt == 'f')
539  array_list_append(a->results,datum);
540  else
541  analysis_datum_free(datum);
542  }
543 
544  do_continue:
545  pbuf_next += strlen("::RESULT\n");
546  remaining -= (pbuf_next - pbuf);
547  /* Skip to next newline-terminated segment, or break out. */
548  pbuf = pbuf_next;
549  if (pbuf >= ebuf) {
550  pbuf = pbuf_next = NULL;
551  break;
552  }
553  else {
554  pbuf_next = strstr(pbuf,"RESULT::");
555  if (pbuf_next)
556  pbuf_next = strstr(pbuf_next + 1,"::RESULT\n");
557  //pbuf_next = strchr(pbuf,'\n');
558  continue;
559  }
560  }
561 
562  /*
563  * Ok, we are done processing; if we have any more input left to
564  * scan, either in a->stdout_buf, or in buf (i.e., !saved), adjust
565  * a->stdout_buf and make sure it has the remnant.
566  */
567  if (remaining > 0) {
568  if (!saved) {
569  new_alen = remaining + 1;
570  if (new_alen % _CB_SAVEBUF_INC > 0)
571  new_alen += new_alen % _CB_SAVEBUF_INC;
572  a->stdout_buf = malloc(new_alen);
573  a->stdout_buf_alen = new_alen;
574  memcpy(a->stdout_buf,pbuf,remaining);
575  a->stdout_buf_len = remaining;
576  a->stdout_buf[a->stdout_buf_len] = '\0';
577 
578  vdebug(8,LA_XML,LF_RPC,
579  "%d bytes remaining; saved; next callback will start with '''%s'''\n",
580  remaining,a->stdout_buf);
581  }
582  else {
583  /*
584  * NB: this should work because memcpy should operate in
585  * wordsize chunks, no more -- and whatever input we
586  * processed already should have been greater than 4 or 8.
587  * So we shouldn't risk an overwrite by copying from the end
588  * of the buffer into its head :).
589  */
590  memcpy(a->stdout_buf,pbuf,remaining);
591  a->stdout_buf_len = remaining;
592  a->stdout_buf[a->stdout_buf_len] = '\0';
593 
594  vdebug(8,LA_XML,LF_RPC,
595  "%d bytes remaining; already saved; next callback will start with '''%s'''\n",
596  remaining,a->stdout_buf);
597  }
598 
599  }
600  else {
601  if (a->stdout_buf) {
602  free(a->stdout_buf);
603  a->stdout_buf = NULL;
604  a->stdout_buf_len = 0;
605  a->stdout_buf_alen = 0;
606 
607  vdebug(8,LA_XML,LF_RPC,
608  "0 bytes remaining; freeing buf!\n");
609  }
610  else {
611  vdebug(8,LA_XML,LF_RPC,
612  "0 bytes remaining; no preexisting buf to free!\n");
613  }
614  }
615 
616  return 0;
617 }
618 
619 int analysis_rpc_stderr_callback(int fd,char *buf,int len,void *state) {
620  struct analysis *a = (struct analysis *)state;
621 
622  // XXX: fill
623 
624  //vdebug(5,LA_XML,LF_RPC,"fd %d recv '%s' (%d)\n",fd,buf,len);
625 
626  return 0;
627 }
628 
629 int vmi1__ListAnalysisDescNames(struct soap *soap,
630  void *_,
632  struct array_list *names;
633  char *name;
634  int i;
635 
636  names = analysis_list_names();
637  if (names && array_list_len(names) > 0) {
638  r->__size_analysisDescName = array_list_len(names);
639  r->analysisDescName =
640  SOAP_CALLOC(soap,r->__size_analysisDescName,sizeof(char *));
641 
642  array_list_foreach(names,i,name) {
643  SOAP_STRCPY(soap,r->analysisDescName[i],name);
644  }
645  }
646  else {
648  r->analysisDescName = NULL;
649  }
650 
651  return SOAP_OK;
652 }
653 
654 int vmi1__ListAnalysisDescs(struct soap *soap,
655  void *_,
656  struct vmi1__AnalysisDescsResponse *r) {
657  struct array_list *descs;
658  struct analysis_desc *desc;
659  int i;
660  GHashTable *reftab;
661 
662  descs = analysis_load_all();
663  if (descs && array_list_len(descs) > 0) {
664  r->__size_analysisDesc = array_list_len(descs);
665  r->analysisDesc =
666  SOAP_CALLOC(soap,r->__size_analysisDesc,sizeof(*r->analysisDesc));
667 
668  reftab = g_hash_table_new(g_direct_hash,g_direct_equal);
669  array_list_foreach(descs,i,desc) {
670  a_analysis_desc_to_x_AnalysisDescT(soap,desc,reftab,
671  &r->analysisDesc[i]);
672  }
673  g_hash_table_destroy(reftab);
674 
675  }
676  else {
677  r->__size_analysisDesc = 0;
678  r->analysisDesc = NULL;
679  }
680 
681  return SOAP_OK;
682 }
683 
684 int vmi1__ListAnalyses(struct soap *soap,
685  void *_,
686  struct vmi1__AnalysesResponse *r) {
687  struct analysis *analysis;
688  int i;
689  GHashTable *reftab;
690  struct array_list *list;
691 
693  r->__size_analysis = list ? array_list_len(list) : 0;
694  if (r->__size_analysis == 0) {
695  r->analysis = NULL;
696  if (list)
697  array_list_free(list);
699  return SOAP_OK;
700  }
701 
702  reftab = g_hash_table_new_full(g_direct_hash,g_direct_equal,NULL,NULL);
703  r->analysis = SOAP_CALLOC(soap,r->__size_analysis,sizeof(*r->analysis));
704  array_list_foreach(list,i,analysis)
705  a_analysis_to_x_AnalysisT(soap,analysis,reftab,&r->analysis[i]);
706 
707  g_hash_table_destroy(reftab);
708  array_list_free(list);
709 
711 
712  return SOAP_OK;
713 }
714 
715 int vmi1__UploadAnalysis(struct soap *soap,
716  struct vmi1__AnalysisDescT *analysisDesc,
717  struct xsd__hexBinary *inputFileContents,
718  struct vmi1__NoneResponse *r) {
719  return soap_receiver_fault(soap,"Not implemented!","Not implemented!");
720 }
721 
722 int vmi1__InstantiateAnalysis(struct soap *soap,
723  struct vmi1__AnalysisSpecT *analysisSpec,
724  struct vmi1__TargetSpecT *targetSpec,
725  struct vmi1__ListenerT *ownerListener,
726  struct vmi1__AnalysisResponse *r) {
727  struct target_spec *ts = NULL;
728  struct analysis_desc *d = NULL;
729  struct analysis_spec *as = NULL;
730  struct analysis *a = NULL;
731  char *path = NULL;
732  int targc = 0;
733  char **targv = NULL;
734  char *binarypath = NULL;
735  int len;
736  int tid;
737  int aid = -1;
738  GHashTable *reftab = NULL;
739  struct monitor *monitor = NULL;
740  struct proxyreq *pr;
741  int fargc = 0;
742  char **fargv = NULL;
743  int i;
744  struct stat statbuf;
745  char *err = NULL, *err_detail = NULL;
746  int locked = 0;
747  char *pbuf = NULL;
748  int fd = -1;
749  int rc = 0;
750  int retval;
751  char *tmpbuf;
752  int pid;
753  int urllen = 0;
754  char *url = NULL;
755  char *atmpdir = NULL;
756  char *wbuf;
757  struct analysis_name_value *ex_nv;
758  struct analysis_param *ex_ap;
759  int ex_sw_argc = 0;
760  int ex_unsw_argc = 0;
761  char **ex_sw_argv = NULL;
762  char **ex_unsw_argv = NULL;
763 
764  pr = soap->user;
765  if (!pr) {
766  err = err_detail = "Request needed splitting but not split!";
767  goto errout;
768  }
769 
770  /*
771  * First, make sure we can find and load the analysis, and that the
772  * target spec is valid enough to get going.
773  */
774 
775  if (!analysisSpec || !analysisSpec->name) {
776  err = err_detail = "Must set an analysis spec name!";
777  goto errout;
778  }
779 
780  if (ownerListener) {
781  if (ownerListener->url != NULL)
782  url = ownerListener->url;
783  else if (ownerListener->hostname != NULL
784  && ownerListener->port != NULL) {
785  urllen = sizeof("http://") + strlen(ownerListener->hostname) \
786  + sizeof(":") + 11 + sizeof(":/vmi/1/analysisListener") + 1;
787  url = malloc(urllen * sizeof(char));
788  snprintf(url,urllen,"http://%s:%d/vmi/1/analysisListener",
789  ownerListener->hostname,*ownerListener->port);
790  }
791  else {
792  return soap_receiver_fault(soap,"Bad listener!","Bad listener!");
793  }
794  }
795 
796  as = x_AnalysisSpecT_to_a_analysis_spec(soap,analysisSpec,reftab,NULL);
797  if (!as) {
798  err = err_detail = "Bad analysis spec!";
799  goto errout;
800  }
801 
802  path = analysis_find(as->name);
803  if (!path) {
804  err = err_detail = "Could not find analysis!";
805  goto errout;
806  }
807 
808  d = analysis_load_pathname(path);
809  if (!d) {
810  err = err_detail = "Could not load analysis description!";
811  goto errout;
812  }
813 
814  /*
815  * If the analysis supports external control, give it a specific
816  * analysis id too! Well, we just grab one no matter what; it's
817  * just we don't care if the monitored child uses it or not if we
818  * know it doesn't support external control -- so we don't pass it
819  * in that case.
820  */
821  aid = monitor_get_unique_objid();
822  as->analysis_id = aid;
823 
824  /*
825  * Deal with analysis inputParams, if any; possibly turn them into
826  * command-line args.
827  */
828  if (as->in_params) {
829  ex_sw_argc = 0;
830  ex_unsw_argc = 0;
831  ex_sw_argv = NULL;
832  ex_unsw_argv = NULL;
833 
834  array_list_foreach(as->in_params,i,ex_nv) {
835  if (!ex_nv->name) {
836  err = err_detail = "Malformed inputParam without name!";
837  goto errout;
838  }
839  if ((d->in_params
840  && (ex_ap = (struct analysis_param *) \
841  g_hash_table_lookup(d->in_params,ex_nv->name)))
842  || (d->in_params_long
843  && (ex_ap = (struct analysis_param *) \
844  g_hash_table_lookup(d->in_params_long,ex_nv->name)))) {
845  if (!ex_ap->is_command_line)
846  continue;
847 
848  if (ex_ap->is_command_line_switched) {
849  ex_sw_argc += 2;
850  ex_sw_argv = realloc(ex_sw_argv,ex_sw_argc * sizeof(char *));
851 
852  /* Prefer long name switches. */
853  if (ex_ap->long_name) {
854  len = strlen(ex_ap->long_name) + 1 + 2;
855  ex_sw_argv[ex_sw_argc - 2] = malloc(len);
856  snprintf(ex_sw_argv[ex_sw_argc - 2],len,
857  "--%s",ex_ap->long_name);
858  }
859  else {
860  len = strlen(ex_ap->name) + 1 + 1;
861  ex_sw_argv[ex_sw_argc - 2] = malloc(len);
862  snprintf(ex_sw_argv[ex_sw_argc - 2],len,
863  "-%s",ex_ap->name);
864  }
865 
866  if (ex_nv->value)
867  ex_sw_argv[ex_sw_argc - 1] = strdup(ex_nv->value);
868  else
869  ex_sw_argv[ex_sw_argc - 1] = strdup("");
870  }
871  else {
872  ++ex_unsw_argc;
873  ex_unsw_argv = realloc(ex_unsw_argv,ex_unsw_argc * sizeof(char *));
874  if (ex_nv->value)
875  ex_unsw_argv[ex_unsw_argc - 1] = strdup(ex_nv->value);
876  else
877  ex_unsw_argv[ex_unsw_argc - 1] = strdup("");
878  }
879  }
880  else {
881  /*
882  * NB: if it's not an analysis param, turn it into a
883  * switched param! :) Do a long param if the name is >
884  * 1; else do a short-switched param.
885  */
886  ex_sw_argc += 2;
887  ex_sw_argv = realloc(ex_sw_argv,ex_sw_argc * sizeof(char *));
888 
889  if (strlen(ex_nv->name) == 1) {
890  len = strlen(ex_nv->name) + 1 + 1;
891  ex_sw_argv[ex_sw_argc - 2] = malloc(len);
892  snprintf(ex_sw_argv[ex_sw_argc - 2],len,"-%s",ex_nv->name);
893  }
894  else {
895  len = strlen(ex_nv->name) + 1 + 2;
896  ex_sw_argv[ex_sw_argc - 2] = malloc(len);
897  snprintf(ex_sw_argv[ex_sw_argc - 2],len,"--%s",ex_nv->name);
898  }
899 
900  if (ex_nv->value)
901  ex_sw_argv[ex_sw_argc - 1] = strdup(ex_nv->value);
902  else
903  ex_sw_argv[ex_sw_argc - 1] = strdup("");
904  }
905  }
906  }
907 
908  /* Setup the analysis binary full path to launch. */
909  len = strlen(path) + 1 + strlen(d->binary) + 1;
910  binarypath = calloc(len,sizeof(char));
911  snprintf(binarypath,len,"%s/%s",path,d->binary);
912 
913  /*
914  * Setup its tmp dir name, but don't create it yet;
915  * <ANALYSIS_TMPDIR>/<name>.<id>
916  */
917  len = strlen(ANALYSIS_TMPDIR) + sizeof("/vmi.analysis.") \
918  + strlen(as->name) + sizeof(".") + 11 + 1 + 11 + 1;
919  atmpdir = malloc(len * sizeof(char));
920  snprintf(atmpdir,len,"%s/vmi.analysis.%s.%d.%u",
921  ANALYSIS_TMPDIR,as->name,aid,rand());
922  if (stat(atmpdir,&statbuf) == 0)
923  vwarn("analysis tmpdir %s already exists!\n",atmpdir);
924 
925  reftab = g_hash_table_new_full(g_direct_hash,g_direct_equal,NULL,NULL);
926 
927  ts = x_TargetSpecT_to_t_target_spec(soap,targetSpec,reftab,NULL);
928  if (!ts) {
929  err = err_detail = "Bad target spec!";
930  goto errout;
931  }
932 
933  /*
934  * Choose a specific target id!
935  */
936  tid = monitor_get_unique_objid();
937  /* Force it to use our new monitored object id. */
938  ts->target_id = tid;
939 
940  /*
941  * Also need to setup the various stdio file args, if necessary.
942  */
943  if (targetSpec->stdinBytes && targetSpec->stdinBytes->__size > 0) {
944  len = strlen(atmpdir) + 1 + sizeof("target.stdin.") + 11 + 1;
945  ts->infile = malloc(len * sizeof(char));
946  snprintf(ts->infile,len,"%s/target.stdin.%u",atmpdir,ts->target_id);
947 
948  /* NB: write the stdin file below, once we have a tmpdir! */
949  }
950  if (targetSpec->logStdout && *targetSpec->logStdout == xsd__boolean__true_) {
951  len = strlen(atmpdir) + 1 + sizeof("target.stdout.") + 11 + 1;
952  ts->outfile = malloc(len * sizeof(char));
953  snprintf(ts->outfile,len,"%s/target.stdout.%u",atmpdir,ts->target_id);
954  }
955  if (targetSpec->logStderr && *targetSpec->logStderr == xsd__boolean__true_) {
956  len = strlen(atmpdir) + 1 + sizeof("target.stderr.") + 11 + 1;
957  ts->errfile = malloc(len * sizeof(char));
958  snprintf(ts->errfile,len,"%s/target.stderr.%u",atmpdir,ts->target_id);
959  }
960 
961  /*
962  * Deal with args.
963  */
964  if (target_spec_to_argv(ts,binarypath,&targc,&targv)) {
965  err = err_detail = "Could not create argv from target spec!";
966  goto errout;
967  }
968 
969  if (d->supports_external_control) {
970  fargc = targc + 3 - 1 + ex_sw_argc + ex_unsw_argc + 1;
971  fargv = calloc(fargc,sizeof(char *));
972  fargv[0] = targv[0];
973  fargv[1] = strdup("-a");
974  fargv[2] = malloc(11);
975  snprintf(fargv[2],11,"%d",aid);
976  memcpy(&fargv[3],&targv[1],sizeof(char *) * (targc - 1));
977  free(targv);
978  targv = NULL;
979  targc += 2;
980  }
981  else {
982  fargc = targc + ex_sw_argc + ex_unsw_argc + 1;
983  fargv = calloc(fargc,sizeof(char *));
984  memcpy(&fargv[0],&targv[0],sizeof(char *) * (targc));
985  free(targv);
986  targv = NULL;
987  }
988 
989  if (ex_sw_argc) {
990  memcpy(&fargv[targc],&ex_sw_argv[0],sizeof(char *) * ex_sw_argc);
991  free(ex_sw_argv);
992  ex_sw_argv = NULL;
993  }
994  /* These should be the last args! */
995  if (ex_unsw_argc) {
996  memcpy(&fargv[targc + ex_sw_argc],&ex_unsw_argv[0],sizeof(char *) * ex_unsw_argc);
997  free(ex_unsw_argv);
998  ex_unsw_argv = NULL;
999  }
1000  /* Make sure the argv is NULL-terminated. */
1001  fargv[targc + ex_sw_argc + ex_unsw_argc] = NULL;
1002 
1003  /*
1004  * Create an analysis instance. Both the monitor and monitored
1005  * child will have one; but analysis->target will only be live in
1006  * the child. That is because the monitor has to monitor the
1007  * analysis binary for results, and maybe report to listeners; its
1008  * RPC functionality is not contained to the child.
1009  *
1010  * So unlike forked targets in the target RPC server, we cannot just
1011  * have a NULL obj.
1012  */
1013  a = analysis_create(as->analysis_id,as,d,tid,NULL);
1014 
1015  /* Save this off so we can grab the logfile names later if needed. */
1016  a->target_spec = ts;
1017 
1018  /*
1019  * Create the analysis tmpdir. This means writing out any support files it
1020  * needs (right now just the target's stdin, if any).
1021  * <ANALYSIS_TMPDIR>/<name>.<id>
1022  */
1023  a->tmpdir = atmpdir;
1024  mkdir(ANALYSIS_TMPDIR,S_IRWXU | S_IRGRP | S_IXGRP);
1025  if (mkdir(a->tmpdir,S_IRWXU | S_IRGRP | S_IXGRP)) {
1026  verror("could not create analysis tmpdir %s: %s!\n",
1027  a->tmpdir,strerror(errno));
1028  err = err_detail = "Could not create analysis tmpdir!";
1029  goto errout;
1030  }
1031 
1032  /*
1033  * Write any support files.
1034  */
1035  if (analysisSpec->supportFiles) {
1036  for (i = 0; i < analysisSpec->supportFiles->__sizesupportFile; ++i) {
1037  len = strlen(a->tmpdir) + sizeof("/")
1038  + strlen(analysisSpec->supportFiles->supportFile[i].name) + 1;
1039  pbuf = malloc(len);
1040  snprintf(pbuf,len,"%s/%s",a->tmpdir,
1041  analysisSpec->supportFiles->supportFile[i].name);
1042  fd = open(pbuf,O_CREAT | O_TRUNC | O_WRONLY,S_IRUSR | S_IWUSR);
1043  if (fd < 0) {
1044  verror("could not open(%s) for write: %s!\n",
1045  pbuf,strerror(errno));
1046  err = err_detail = "Could not write file!";
1047  goto errout;
1048  }
1049 
1050  rc = 0;
1051  len = analysisSpec->supportFiles->supportFile[i].content.__size;
1052  wbuf = (char *)analysisSpec->supportFiles->supportFile[i].content.__ptr;
1053  while (rc < len) {
1054  retval = write(fd,wbuf + rc,len - rc);
1055  if (retval < 0) {
1056  if (errno == EINTR)
1057  continue;
1058  else {
1059  verror("write(%s): %s\n",pbuf,strerror(errno));
1060  err = err_detail = \
1061  "Could not finish writing source file in tmpdir!";
1062  close(fd);
1063  goto errout;
1064  }
1065  }
1066  else
1067  rc += retval;
1068  }
1069  close(fd);
1070  free(pbuf);
1071  }
1072  }
1073 
1074  if (targetSpec->stdinBytes && targetSpec->stdinBytes->__size > 0) {
1075  len = strlen(a->tmpdir) + sizeof("/") + strlen(ts->infile) + 1;
1076  pbuf = malloc(len);
1077  snprintf(pbuf,len,"%s/%s",a->tmpdir,ts->infile);
1078 
1079  /* Write the stdin file now that we have a tmpdir */
1080  fd = open(pbuf,O_CREAT | O_TRUNC | O_WRONLY,S_IRUSR | S_IWUSR | S_IRGRP);
1081  if (fd < 0) {
1082  verror("open(%s): %s\n",pbuf,strerror(errno));
1083  err = err_detail = "Could not save target stdin in tmpdir!";
1084  goto errout;
1085  }
1086 
1087  while (rc < targetSpec->stdinBytes->__size) {
1088  retval = write(fd,targetSpec->stdinBytes->__ptr + rc,
1089  targetSpec->stdinBytes->__size - rc);
1090  if (retval < 0) {
1091  if (errno == EINTR)
1092  continue;
1093  else {
1094  verror("write(%s): %s\n",pbuf,strerror(errno));
1095  err = err_detail = \
1096  "Could not finish writing target stdin in tmpdir!";
1097  close(fd);
1098  goto errout;
1099  }
1100  }
1101  else
1102  rc += retval;
1103  }
1104  close(fd);
1105  }
1106 
1108  locked = 1;
1109 
1110  /*
1111  * We have to setup a monitor that will exec the analysis binary.
1112  *
1113  * If the analysis supports external control, we need to choose a
1114  *
1115  * Also, we need to register/bind the ownerListener (and any
1116  * subsequent listeners) in this server, and in the forked program.
1117  * Why? So that the monitor thread can autoparse results from the
1118  * analysis's stdout/err, AND so that the analysis itself can
1119  * generate results. This does suck, but we don't want to be in the
1120  * business of forwarding results from the monitored analysis to the
1121  * monitor thread. No reason to, especially since we've set it up
1122  * so that the monitored analysis can itself receive RPCs!
1123  */
1124 
1126  aid,MONITOR_OBJTYPE_ANALYSIS,a,NULL);
1127  if (!monitor) {
1128  err = err_detail = "Could not create analysis monitor!";
1129  goto errout;
1130  }
1131 
1132  /*
1133  * XXX: eventually, for analyses that support external control,
1134  * we'll have to forward the ownerListener URL to them!
1135  */
1137  err = err_detail = "Could not bind to analysis (monitor)!";
1138  goto errout;
1139  }
1140 
1141  /*
1142  * Setup I/O to child! We always have to use our callbacks and
1143  * do our own logging. BUT, we want to log/interact with the
1144  * spawned analysis's I/O, AND those of any analysis-spawned
1145  * targets. Sigh... for now we get lucky by 1) setting up analysis
1146  * stdin if desired, and 2) assuming a single target per analysis,
1147  * and using the target command-line API to specify a stdin file,
1148  * and by writing that tmp file into our analysis tmpdir.
1149  *
1150  * Eventually, we will either need to extend the command line to be
1151  * able specify multiple targets, or to write targetSpec files into
1152  * the analysis tmpdir, or something else -- setup stdin pipes? :)
1153  */
1154 
1155  if (analysisSpec->stdinBytes && analysisSpec->stdinBytes->__size > 0) {
1156  tmpbuf = malloc(analysisSpec->stdinBytes->__size);
1157  memcpy(tmpbuf,analysisSpec->stdinBytes->__ptr,
1158  analysisSpec->stdinBytes->__size);
1159 
1160  monitor_setup_stdin(monitor,tmpbuf,analysisSpec->stdinBytes->__size);
1161  tmpbuf = NULL;
1162  }
1163  if (analysisSpec->logStdout
1164  && analysisSpec->logStdout == xsd__boolean__true_) {
1165  len = strlen(a->tmpdir) + sizeof("/analysis.stdout.") + 11 + 1;
1166  as->outfile = malloc(len);
1167  snprintf(as->outfile,len,"%s/analysis.stdout.%d",a->tmpdir,aid);
1168 
1169  monitor_setup_stdout(monitor,-1,as->outfile,
1171  }
1172  if (analysisSpec->logStderr
1173  && analysisSpec->logStderr == xsd__boolean__true_) {
1174  len = strlen(a->tmpdir) + sizeof("/analysis.stderr.") + 11 + 1;
1175  as->errfile = malloc(len);
1176  snprintf(as->errfile,len,"%s/analysis.stderr.%d",a->tmpdir,aid);
1177 
1178  monitor_setup_stderr(monitor,-1,as->errfile,
1180  }
1181 
1183 
1184  pid = monitor_spawn(monitor,binarypath,fargv,NULL,a->tmpdir);
1185  if (pid < 0) {
1186  verror("error spawning: %d (%s)\n",pid,strerror(errno));
1187  err = err_detail = "Could not spawn analysis!";
1188  goto errout;
1189  }
1190 
1191  proxyreq_attach_new_objid(pr,aid,monitor);
1192 
1193  r->analysis = a_analysis_to_x_AnalysisT(soap,a,reftab,NULL);
1195 
1196  return SOAP_OK;
1197 
1198  errout:
1199  /* Cleanup! */
1200 
1201  if (ex_unsw_argv) {
1202  for (i = 0; i < ex_unsw_argc; ++i)
1203  if (ex_unsw_argv[i])
1204  free(ex_unsw_argv[i]);
1205  free(ex_unsw_argv);
1206  }
1207  if (ex_sw_argv) {
1208  for (i = 0; i < ex_sw_argc; ++i)
1209  if (ex_sw_argv[i])
1210  free(ex_sw_argv[i]);
1211  free(ex_sw_argv);
1212  }
1213 
1214  if (fargc > 0) {
1215  for (i = 0; i < fargc; ++i)
1216  if (fargv[i])
1217  free(fargv[i]);
1218  free(fargv);
1219  }
1220  if (a) {
1221  analysis_free(a);
1222  }
1223  else {
1224  if (atmpdir)
1225  free(atmpdir);
1226  if (as)
1227  analysis_spec_free(as);
1228  if (d)
1229  analysis_desc_free(d);
1230  if (ts)
1231  target_free_spec(ts);
1232  }
1233  if (reftab)
1234  g_hash_table_destroy(reftab);
1235  if (binarypath)
1236  free(binarypath);
1237  if (path)
1238  free(path);
1239  if (pbuf)
1240  free(pbuf);
1241  if (url)
1243  if (urllen)
1244  free(url);
1245 
1246  if (locked)
1248 
1249  return soap_receiver_fault(soap,err,err_detail);
1250 }
1251 
1253  struct vmi1__AnalysisSpecT *analysisSpec,
1254  struct vmi1__TargetSpecT *targetSpec,
1255  struct vmi1__TargetSpecT *overlayTargetSpec,
1256  vmi1__ThreadIdT baseThid,
1257  char *baseThreadName,
1258  vmi1__ListenerT *ownerListener,
1259  struct vmi1__AnalysisResponse *r) {
1260  struct target_spec *ts = NULL;
1261  struct target_spec *ots = NULL;
1262  struct analysis_desc *d = NULL;
1263  struct analysis_spec *as = NULL;
1264  struct analysis *a = NULL;
1265  char *path = NULL;
1266  int targc = 0;
1267  char **targv = NULL;
1268  int otargc = 0;
1269  char **otargv = NULL;
1270  int otrc;
1271  char otbuf[256];
1272  char *binarypath = NULL;
1273  int len;
1274  int tid;
1275  int aid = -1;
1276  GHashTable *reftab = NULL;
1277  struct monitor *monitor = NULL;
1278  struct proxyreq *pr;
1279  int fargc = 0;
1280  char **fargv = NULL;
1281  int i;
1282  struct stat statbuf;
1283  char *err = NULL, *err_detail = NULL;
1284  int locked = 0;
1285  char *pbuf = NULL;
1286  int fd = -1;
1287  int rc = 0;
1288  int retval;
1289  char *tmpbuf;
1290  int pid;
1291  int urllen = 0;
1292  char *url = NULL;
1293  char *atmpdir = NULL;
1294  char *wbuf;
1295  struct analysis_name_value *ex_nv;
1296  struct analysis_param *ex_ap;
1297  int ex_sw_argc = 0;
1298  int ex_unsw_argc = 0;
1299  char **ex_sw_argv = NULL;
1300  char **ex_unsw_argv = NULL;
1301 
1302  pr = soap->user;
1303  if (!pr) {
1304  err = err_detail = "Request needed splitting but not split!";
1305  goto errout;
1306  }
1307 
1308  /*
1309  * First, make sure we can find and load the analysis, and that the
1310  * target spec is valid enough to get going.
1311  */
1312 
1313  if (!analysisSpec || !analysisSpec->name) {
1314  err = err_detail = "Must set an analysis spec name!";
1315  goto errout;
1316  }
1317 
1318  if (ownerListener) {
1319  if (ownerListener->url != NULL)
1320  url = ownerListener->url;
1321  else if (ownerListener->hostname != NULL
1322  && ownerListener->port != NULL) {
1323  urllen = sizeof("http://") + strlen(ownerListener->hostname) \
1324  + sizeof(":") + 11 + sizeof(":/vmi/1/analysisListener") + 1;
1325  url = malloc(urllen * sizeof(char));
1326  snprintf(url,urllen,"http://%s:%d/vmi/1/analysisListener",
1327  ownerListener->hostname,*ownerListener->port);
1328  }
1329  else {
1330  return soap_receiver_fault(soap,"Bad listener!","Bad listener!");
1331  }
1332  }
1333 
1334  as = x_AnalysisSpecT_to_a_analysis_spec(soap,analysisSpec,reftab,NULL);
1335  if (!as) {
1336  err = err_detail = "Bad analysis spec!";
1337  goto errout;
1338  }
1339 
1340  path = analysis_find(as->name);
1341  if (!path) {
1342  err = err_detail = "Could not find analysis!";
1343  goto errout;
1344  }
1345 
1346  d = analysis_load_pathname(path);
1347  if (!d) {
1348  err = err_detail = "Could not load analysis description!";
1349  goto errout;
1350  }
1351 
1352  /*
1353  * If the analysis supports external control, give it a specific
1354  * analysis id too! Well, we just grab one no matter what; it's
1355  * just we don't care if the monitored child uses it or not if we
1356  * know it doesn't support external control -- so we don't pass it
1357  * in that case.
1358  */
1359  aid = monitor_get_unique_objid();
1360  as->analysis_id = aid;
1361 
1362  /*
1363  * Deal with analysis inputParams, if any; possibly turn them into
1364  * command-line args.
1365  */
1366  if (as->in_params) {
1367  ex_sw_argc = 0;
1368  ex_unsw_argc = 0;
1369  ex_sw_argv = NULL;
1370  ex_unsw_argv = NULL;
1371 
1372  array_list_foreach(as->in_params,i,ex_nv) {
1373  if (!ex_nv->name) {
1374  err = err_detail = "Malformed inputParam without name!";
1375  goto errout;
1376  }
1377  if ((d->in_params
1378  && (ex_ap = (struct analysis_param *) \
1379  g_hash_table_lookup(d->in_params,ex_nv->name)))
1380  || (d->in_params_long
1381  && (ex_ap = (struct analysis_param *) \
1382  g_hash_table_lookup(d->in_params_long,ex_nv->name)))) {
1383  if (!ex_ap->is_command_line)
1384  continue;
1385 
1386  if (ex_ap->is_command_line_switched) {
1387  ex_sw_argc += 2;
1388  ex_sw_argv = realloc(ex_sw_argv,ex_sw_argc * sizeof(char *));
1389 
1390  /* Prefer long name switches. */
1391  if (ex_ap->long_name) {
1392  len = strlen(ex_ap->long_name) + 1 + 2;
1393  ex_sw_argv[ex_sw_argc - 2] = malloc(len);
1394  snprintf(ex_sw_argv[ex_sw_argc - 2],len,
1395  "--%s",ex_ap->long_name);
1396  }
1397  else {
1398  len = strlen(ex_ap->name) + 1 + 1;
1399  ex_sw_argv[ex_sw_argc - 2] = malloc(len);
1400  snprintf(ex_sw_argv[ex_sw_argc - 2],len,
1401  "-%s",ex_ap->name);
1402  }
1403 
1404  if (ex_nv->value)
1405  ex_sw_argv[ex_sw_argc - 1] = strdup(ex_nv->value);
1406  else
1407  ex_sw_argv[ex_sw_argc - 1] = strdup("");
1408  }
1409  else {
1410  ++ex_unsw_argc;
1411  ex_unsw_argv = realloc(ex_unsw_argv,ex_unsw_argc * sizeof(char *));
1412  if (ex_nv->value)
1413  ex_unsw_argv[ex_unsw_argc - 1] = strdup(ex_nv->value);
1414  else
1415  ex_unsw_argv[ex_unsw_argc - 1] = strdup("");
1416  }
1417  }
1418  else {
1419  /*
1420  * NB: if it's not an analysis param, turn it into a
1421  * switched param! :) Do a long param if the name is >
1422  * 1; else do a short-switched param.
1423  */
1424  ex_sw_argc += 2;
1425  ex_sw_argv = realloc(ex_sw_argv,ex_sw_argc * sizeof(char *));
1426 
1427  if (strlen(ex_nv->name) == 1) {
1428  len = strlen(ex_nv->name) + 1 + 1;
1429  ex_sw_argv[ex_sw_argc - 2] = malloc(len);
1430  snprintf(ex_sw_argv[ex_sw_argc - 2],len,"-%s",ex_nv->name);
1431  }
1432  else {
1433  len = strlen(ex_nv->name) + 1 + 2;
1434  ex_sw_argv[ex_sw_argc - 2] = malloc(len);
1435  snprintf(ex_sw_argv[ex_sw_argc - 2],len,"--%s",ex_nv->name);
1436  }
1437 
1438  if (ex_nv->value)
1439  ex_sw_argv[ex_sw_argc - 1] = strdup(ex_nv->value);
1440  else
1441  ex_sw_argv[ex_sw_argc - 1] = strdup("");
1442  }
1443  }
1444  }
1445 
1446  /* Setup the analysis binary full path to launch. */
1447  len = strlen(path) + 1 + strlen(d->binary) + 1;
1448  binarypath = calloc(len,sizeof(char));
1449  snprintf(binarypath,len,"%s/%s",path,d->binary);
1450 
1451  /*
1452  * Setup its tmp dir name, but don't create it yet;
1453  * <ANALYSIS_TMPDIR>/<name>.<id>
1454  */
1455  len = strlen(ANALYSIS_TMPDIR) + sizeof("/vmi.analysis.") \
1456  + strlen(as->name) + sizeof(".") + 11 + 1 + 11 + 1;
1457  atmpdir = malloc(len * sizeof(char));
1458  snprintf(atmpdir,len,"%s/vmi.analysis.%s.%d.%u",
1459  ANALYSIS_TMPDIR,as->name,aid,rand());
1460  if (stat(atmpdir,&statbuf) == 0)
1461  vwarn("analysis tmpdir %s already exists!\n",atmpdir);
1462 
1463  reftab = g_hash_table_new_full(g_direct_hash,g_direct_equal,NULL,NULL);
1464 
1465  ts = x_TargetSpecT_to_t_target_spec(soap,targetSpec,reftab,NULL);
1466  if (!ts) {
1467  err = err_detail = "Bad target spec!";
1468  goto errout;
1469  }
1470 
1471  ots = x_TargetSpecT_to_t_target_spec(soap,overlayTargetSpec,reftab,NULL);
1472  if (!ots) {
1473  err = err_detail = "Bad overlay target spec!";
1474  goto errout;
1475  }
1476 
1477  /*
1478  * Choose a specific target id!
1479  */
1480  tid = monitor_get_unique_objid();
1481  /* Force it to use our new monitored object id. */
1482  ts->target_id = tid;
1483 
1484  /*
1485  * Also need to setup the various stdio file args, if necessary.
1486  */
1487  if (targetSpec->stdinBytes && targetSpec->stdinBytes->__size > 0) {
1488  len = strlen(atmpdir) + 1 + sizeof("target.stdin.") + 11 + 1;
1489  ts->infile = malloc(len * sizeof(char));
1490  snprintf(ts->infile,len,"%s/target.stdin.%u",atmpdir,ts->target_id);
1491 
1492  /* NB: write the stdin file below, once we have a tmpdir! */
1493  }
1494  else if (overlayTargetSpec->stdinBytes
1495  && overlayTargetSpec->stdinBytes->__size > 0) {
1496  len = strlen(atmpdir) + 1 + sizeof("target.stdin.") + 11 + 1;
1497  ts->infile = malloc(len * sizeof(char));
1498  snprintf(ts->infile,len,"%s/target.stdin.%u",atmpdir,ts->target_id);
1499 
1500  /* NB: write the stdin file below, once we have a tmpdir! */
1501  }
1502  if (targetSpec->logStdout && *targetSpec->logStdout == xsd__boolean__true_) {
1503  len = strlen(atmpdir) + 1 + sizeof("target.stdout.") + 11 + 1;
1504  ts->outfile = malloc(len * sizeof(char));
1505  snprintf(ts->outfile,len,"%s/target.stdout.%u",atmpdir,ts->target_id);
1506  }
1507  else if (overlayTargetSpec->logStdout
1508  && *overlayTargetSpec->logStdout == xsd__boolean__true_) {
1509  len = strlen(atmpdir) + 1 + sizeof("target.stdout.") + 11 + 1;
1510  ts->outfile = malloc(len * sizeof(char));
1511  snprintf(ts->outfile,len,"%s/target.stdout.%u",atmpdir,ts->target_id);
1512  }
1513  if (targetSpec->logStderr && *targetSpec->logStderr == xsd__boolean__true_) {
1514  len = strlen(atmpdir) + 1 + sizeof("target.stderr.") + 11 + 1;
1515  ts->errfile = malloc(len * sizeof(char));
1516  snprintf(ts->errfile,len,"%s/target.stderr.%u",atmpdir,ts->target_id);
1517  }
1518  else if (overlayTargetSpec->logStderr
1519  && *overlayTargetSpec->logStderr == xsd__boolean__true_) {
1520  len = strlen(atmpdir) + 1 + sizeof("target.stderr.") + 11 + 1;
1521  ts->errfile = malloc(len * sizeof(char));
1522  snprintf(ts->errfile,len,"%s/target.stderr.%u",atmpdir,ts->target_id);
1523  }
1524 
1525  if (target_spec_to_argv(ts,binarypath,&targc,&targv)) {
1526  err = err_detail = "Could not create argv from target spec!";
1527  goto errout;
1528  }
1529  if (target_spec_to_argv(ots,binarypath,&otargc,&otargv)) {
1530  err = err_detail = "Could not create argv from overlay target spec!";
1531  goto errout;
1532  }
1533 
1534  /*
1535  * Deal with args.
1536  */
1537  if (d->supports_external_control) {
1538  fargc = targc + 2 + 3 - 1 + ex_sw_argc + ex_unsw_argc + 1;
1539  fargv = calloc(fargc,sizeof(char *));
1540  fargv[0] = targv[0];
1541  fargv[1] = strdup("-a");
1542  fargv[2] = malloc(11);
1543  snprintf(fargv[2],11,"%d",aid);
1544  memcpy(&fargv[3],&targv[1],sizeof(char *) * (targc - 1));
1545  free(targv);
1546  targv = NULL;
1547  targc += 2;
1548  }
1549  else {
1550  fargc = targc + 2 + ex_sw_argc + ex_unsw_argc + 1;
1551  fargv = calloc(fargc,sizeof(char *));
1552  memcpy(&fargv[0],&targv[0],sizeof(char *) * (targc));
1553  free(targv);
1554  targv = NULL;
1555  }
1556 
1557  fargv[targc++] = strdup("--overlay");
1558 
1559  otrc = 0;
1560  //otrc += snprintf(otbuf + otrc,sizeof(otbuf) - otrc,"'");
1561  if (baseThreadName)
1562  otrc += snprintf(otbuf + otrc,sizeof(otbuf) - otrc,
1563  "%s:",baseThreadName);
1564  else
1565  otrc += snprintf(otbuf + otrc,sizeof(otbuf) - otrc,
1566  "%d:",baseThid);
1567  for (i = 1; i < otargc; ++i) {
1568  otrc += snprintf(otbuf + otrc,sizeof(otbuf) - otrc," %s",otargv[i]);
1569  }
1570  //otrc += snprintf(otbuf + otrc,sizeof(otbuf) - otrc,"'");
1571 
1572  fargv[targc++] = strdup(otbuf);
1573 
1574  if (ex_sw_argc) {
1575  memcpy(&fargv[targc],&ex_sw_argv[0],sizeof(char *) * ex_sw_argc);
1576  free(ex_sw_argv);
1577  ex_sw_argv = NULL;
1578  }
1579  /* These should be the last args! */
1580  if (ex_unsw_argc) {
1581  memcpy(&fargv[targc + ex_sw_argc],&ex_unsw_argv[0],sizeof(char *) * ex_unsw_argc);
1582  free(ex_unsw_argv);
1583  ex_unsw_argv = NULL;
1584  }
1585  /* Make sure the argv is NULL-terminated. */
1586  fargv[targc + ex_sw_argc + ex_unsw_argc] = NULL;
1587 
1588  /*
1589  * Create an analysis instance. Both the monitor and monitored
1590  * child will have one; but analysis->target will only be live in
1591  * the child. That is because the monitor has to monitor the
1592  * analysis binary for results, and maybe report to listeners; its
1593  * RPC functionality is not contained to the child.
1594  *
1595  * So unlike forked targets in the target RPC server, we cannot just
1596  * have a NULL obj.
1597  */
1598  a = analysis_create(as->analysis_id,as,d,tid,NULL);
1599 
1600  /* Save this off so we can grab the logfile names later if needed. */
1601  a->target_spec = ts;
1602  a->overlay_target_spec = ts;
1603 
1604  /*
1605  * Create the analysis tmpdir. This means writing out any support files it
1606  * needs (right now just the target's stdin, if any).
1607  * <ANALYSIS_TMPDIR>/<name>.<id>
1608  */
1609  a->tmpdir = atmpdir;
1610  mkdir(ANALYSIS_TMPDIR,S_IRWXU | S_IRGRP | S_IXGRP);
1611  if (mkdir(a->tmpdir,S_IRWXU | S_IRGRP | S_IXGRP)) {
1612  verror("could not create analysis tmpdir %s: %s!\n",
1613  a->tmpdir,strerror(errno));
1614  err = err_detail = "Could not create analysis tmpdir!";
1615  goto errout;
1616  }
1617 
1618  /*
1619  * Write any support files.
1620  */
1621  if (analysisSpec->supportFiles) {
1622  for (i = 0; i < analysisSpec->supportFiles->__sizesupportFile; ++i) {
1623  len = strlen(a->tmpdir) + sizeof("/")
1624  + strlen(analysisSpec->supportFiles->supportFile[i].name) + 1;
1625  pbuf = malloc(len);
1626  snprintf(pbuf,len,"%s/%s",a->tmpdir,
1627  analysisSpec->supportFiles->supportFile[i].name);
1628  fd = open(pbuf,O_CREAT | O_TRUNC | O_WRONLY,S_IRUSR | S_IWUSR);
1629  if (fd < 0) {
1630  verror("could not open(%s) for write: %s!\n",
1631  pbuf,strerror(errno));
1632  err = err_detail = "Could not write file!";
1633  goto errout;
1634  }
1635 
1636  rc = 0;
1637  len = analysisSpec->supportFiles->supportFile[i].content.__size;
1638  wbuf = (char *)analysisSpec->supportFiles->supportFile[i].content.__ptr;
1639  while (rc < len) {
1640  retval = write(fd,wbuf + rc,len - rc);
1641  if (retval < 0) {
1642  if (errno == EINTR)
1643  continue;
1644  else {
1645  verror("write(%s): %s\n",pbuf,strerror(errno));
1646  err = err_detail = \
1647  "Could not finish writing source file in tmpdir!";
1648  close(fd);
1649  goto errout;
1650  }
1651  }
1652  else
1653  rc += retval;
1654  }
1655  close(fd);
1656  free(pbuf);
1657  }
1658  }
1659 
1660  if (targetSpec->stdinBytes && targetSpec->stdinBytes->__size > 0) {
1661  len = strlen(a->tmpdir) + sizeof("/") + strlen(ts->infile) + 1;
1662  pbuf = malloc(len);
1663  snprintf(pbuf,len,"%s/%s",a->tmpdir,ts->infile);
1664 
1665  /* Write the stdin file now that we have a tmpdir */
1666  fd = open(pbuf,O_CREAT | O_TRUNC | O_WRONLY,S_IRUSR | S_IWUSR | S_IRGRP);
1667  if (fd < 0) {
1668  verror("open(%s): %s\n",pbuf,strerror(errno));
1669  err = err_detail = "Could not save target stdin in tmpdir!";
1670  goto errout;
1671  }
1672 
1673  while (rc < targetSpec->stdinBytes->__size) {
1674  retval = write(fd,targetSpec->stdinBytes->__ptr + rc,
1675  targetSpec->stdinBytes->__size - rc);
1676  if (retval < 0) {
1677  if (errno == EINTR)
1678  continue;
1679  else {
1680  verror("write(%s): %s\n",pbuf,strerror(errno));
1681  err = err_detail = \
1682  "Could not finish writing target stdin in tmpdir!";
1683  close(fd);
1684  goto errout;
1685  }
1686  }
1687  else
1688  rc += retval;
1689  }
1690  close(fd);
1691  }
1692  else if (overlayTargetSpec->stdinBytes
1693  && overlayTargetSpec->stdinBytes->__size > 0) {
1694  len = strlen(a->tmpdir) + sizeof("/") + strlen(ts->infile) + 1;
1695  pbuf = malloc(len);
1696  snprintf(pbuf,len,"%s/%s",a->tmpdir,ts->infile);
1697 
1698  /* Write the stdin file now that we have a tmpdir */
1699  fd = open(pbuf,O_CREAT | O_TRUNC | O_WRONLY,S_IRUSR | S_IWUSR | S_IRGRP);
1700  if (fd < 0) {
1701  verror("open(%s): %s\n",pbuf,strerror(errno));
1702  err = err_detail = "Could not save target stdin in tmpdir!";
1703  goto errout;
1704  }
1705 
1706  while (rc < overlayTargetSpec->stdinBytes->__size) {
1707  retval = write(fd,overlayTargetSpec->stdinBytes->__ptr + rc,
1708  overlayTargetSpec->stdinBytes->__size - rc);
1709  if (retval < 0) {
1710  if (errno == EINTR)
1711  continue;
1712  else {
1713  verror("write(%s): %s\n",pbuf,strerror(errno));
1714  err = err_detail = \
1715  "Could not finish writing target stdin in tmpdir!";
1716  close(fd);
1717  goto errout;
1718  }
1719  }
1720  else
1721  rc += retval;
1722  }
1723  close(fd);
1724  }
1725 
1727  locked = 1;
1728 
1729  /*
1730  * We have to setup a monitor that will exec the analysis binary.
1731  *
1732  * If the analysis supports external control, we need to choose a
1733  *
1734  * Also, we need to register/bind the ownerListener (and any
1735  * subsequent listeners) in this server, and in the forked program.
1736  * Why? So that the monitor thread can autoparse results from the
1737  * analysis's stdout/err, AND so that the analysis itself can
1738  * generate results. This does suck, but we don't want to be in the
1739  * business of forwarding results from the monitored analysis to the
1740  * monitor thread. No reason to, especially since we've set it up
1741  * so that the monitored analysis can itself receive RPCs!
1742  */
1743 
1745  aid,MONITOR_OBJTYPE_ANALYSIS,a,NULL);
1746  if (!monitor) {
1747  err = err_detail = "Could not create analysis monitor!";
1748  goto errout;
1749  }
1750 
1751  /*
1752  * XXX: eventually, for analyses that support external control,
1753  * we'll have to forward the ownerListener URL to them!
1754  */
1756  err = err_detail = "Could not bind to analysis (monitor)!";
1757  goto errout;
1758  }
1759 
1760  /*
1761  * Setup I/O to child! We always have to use our callbacks and
1762  * do our own logging. BUT, we want to log/interact with the
1763  * spawned analysis's I/O, AND those of any analysis-spawned
1764  * targets. Sigh... for now we get lucky by 1) setting up analysis
1765  * stdin if desired, and 2) assuming a single target per analysis,
1766  * and using the target command-line API to specify a stdin file,
1767  * and by writing that tmp file into our analysis tmpdir.
1768  *
1769  * Eventually, we will either need to extend the command line to be
1770  * able specify multiple targets, or to write targetSpec files into
1771  * the analysis tmpdir, or something else -- setup stdin pipes? :)
1772  */
1773 
1774  if (analysisSpec->stdinBytes && analysisSpec->stdinBytes->__size > 0) {
1775  tmpbuf = malloc(analysisSpec->stdinBytes->__size);
1776  memcpy(tmpbuf,analysisSpec->stdinBytes->__ptr,
1777  analysisSpec->stdinBytes->__size);
1778 
1779  monitor_setup_stdin(monitor,tmpbuf,analysisSpec->stdinBytes->__size);
1780  tmpbuf = NULL;
1781  }
1782  if (analysisSpec->logStdout
1783  && analysisSpec->logStdout == xsd__boolean__true_) {
1784  len = strlen(a->tmpdir) + sizeof("/analysis.stdout.") + 11 + 1;
1785  as->outfile = malloc(len);
1786  snprintf(as->outfile,len,"%s/analysis.stdout.%d",a->tmpdir,aid);
1787 
1788  monitor_setup_stdout(monitor,-1,as->outfile,
1790  }
1791  if (analysisSpec->logStderr
1792  && analysisSpec->logStderr == xsd__boolean__true_) {
1793  len = strlen(a->tmpdir) + sizeof("/analysis.stderr.") + 11 + 1;
1794  as->errfile = malloc(len);
1795  snprintf(as->errfile,len,"%s/analysis.stderr.%d",a->tmpdir,aid);
1796 
1797  monitor_setup_stderr(monitor,-1,as->errfile,
1799  }
1800 
1802 
1803  pid = monitor_spawn(monitor,binarypath,fargv,NULL,a->tmpdir);
1804  if (pid < 0) {
1805  verror("error spawning: %d (%s)\n",pid,strerror(errno));
1806  err = err_detail = "Could not spawn analysis!";
1807  goto errout;
1808  }
1809 
1810  proxyreq_attach_new_objid(pr,aid,monitor);
1811 
1812  r->analysis = a_analysis_to_x_AnalysisT(soap,a,reftab,NULL);
1814 
1815  return SOAP_OK;
1816 
1817  errout:
1818  /* Cleanup! */
1819 
1820  if (ex_unsw_argv) {
1821  for (i = 0; i < ex_unsw_argc; ++i)
1822  if (ex_unsw_argv[i])
1823  free(ex_unsw_argv[i]);
1824  free(ex_unsw_argv);
1825  }
1826  if (ex_sw_argv) {
1827  for (i = 0; i < ex_sw_argc; ++i)
1828  if (ex_sw_argv[i])
1829  free(ex_sw_argv[i]);
1830  free(ex_sw_argv);
1831  }
1832 
1833  if (fargc > 0) {
1834  for (i = 0; i < fargc; ++i)
1835  if (fargv[i])
1836  free(fargv[i]);
1837  free(fargv);
1838  }
1839  if (a) {
1840  analysis_free(a);
1841  }
1842  else {
1843  if (atmpdir)
1844  free(atmpdir);
1845  if (as)
1846  analysis_spec_free(as);
1847  if (d)
1848  analysis_desc_free(d);
1849  if (ts)
1850  target_free_spec(ts);
1851  }
1852  if (reftab)
1853  g_hash_table_destroy(reftab);
1854  if (binarypath)
1855  free(binarypath);
1856  if (path)
1857  free(path);
1858  if (pbuf)
1859  free(pbuf);
1860  if (url)
1862  if (urllen)
1863  free(url);
1864 
1865  if (locked)
1867 
1868  return soap_receiver_fault(soap,err,err_detail);
1869 }
1870 
1871 int vmi1__InstantiateOverlayAnalysis(struct soap *soap,
1872  struct vmi1__AnalysisSpecT *analysisSpec,
1873  struct vmi1__TargetSpecT *targetSpec,
1874  struct vmi1__TargetSpecT *overlayTargetSpec,
1875  vmi1__ThreadIdT baseThid,
1876  vmi1__ListenerT *ownerListener,
1877  struct vmi1__AnalysisResponse *r) {
1878  return __vmi1__InstantiateOverlayAnalysis(soap,analysisSpec,targetSpec,
1879  overlayTargetSpec,
1880  baseThid,NULL,
1881  ownerListener,r);
1882 }
1883 
1885  struct vmi1__AnalysisSpecT *analysisSpec,
1886  struct vmi1__TargetSpecT *targetSpec,
1887  struct vmi1__TargetSpecT *overlayTargetSpec,
1888  char *baseThreadName,
1889  vmi1__ListenerT *ownerListener,
1890  struct vmi1__AnalysisResponse *r) {
1891  return __vmi1__InstantiateOverlayAnalysis(soap,analysisSpec,targetSpec,
1892  overlayTargetSpec,
1893  -1,baseThreadName,
1894  ownerListener,r);
1895 }
1896 
1897 int vmi1__PauseAnalysis(struct soap *soap,
1898  vmi1__AnalysisIdT aid,
1899  struct vmi1__NoneResponse *r) {
1900  struct analysis *a = NULL;
1901  struct monitor *monitor;
1902  char *errmsg;
1903 
1905  (void **)&a,&monitor)) {
1906  return soap_receiver_fault(soap,"Nonexistent analysis!",
1907  "Specified analysis does not exist!");
1908  }
1909 
1910  if (a->desc->supports_external_control) {
1911  PROXY_REQUEST_LOCKED(soap,aid,&analysis_rpc_mutex);
1912 
1913  monitor_close_obj(monitor,a,0,0);
1914  }
1915  else {
1916  /*
1917  * Try our best to pause it via SIGSTOP.
1918  */
1919  if (a->status == ASTATUS_PAUSED) {
1920  errmsg = "Analysis already paused!";
1921  goto errout;
1922  }
1923  else if (a->status == ASTATUS_DONE) {
1924  errmsg = "Analysis already done; cannot pause!";
1925  goto errout;
1926  }
1927 
1928  if (kill(monitor->p.pid,SIGSTOP) < 0) {
1929  if (errno == ESRCH) {
1930  errmsg = "Analysis seems dead; cannot pause!";
1931  goto errout;
1932  }
1933  else {
1934  errmsg = "Error pausing analysis!";
1935  goto errout;
1936  }
1937  }
1939  }
1940 
1942 
1943  return SOAP_OK;
1944 
1945  errout:
1947 
1948  return soap_receiver_fault(soap,errmsg,errmsg);
1949 }
1950 
1951 int vmi1__ResumeAnalysis(struct soap *soap,
1952  vmi1__AnalysisIdT aid,
1953  struct vmi1__NoneResponse *r) {
1954  struct analysis *a = NULL;
1955  struct monitor *monitor;
1956  char *errmsg;
1957 
1959  (void **)&a,&monitor)) {
1960  return soap_receiver_fault(soap,"Nonexistent analysis!",
1961  "Specified analysis does not exist!");
1962  }
1963 
1964  if (a->desc->supports_external_control) {
1965  PROXY_REQUEST_LOCKED(soap,aid,&analysis_rpc_mutex);
1966 
1967  monitor_close_obj(monitor,a,0,0);
1968  }
1969  else {
1970  /*
1971  * Try our best to pause it via SIGCONT.
1972  */
1973  if (a->status == ASTATUS_RUNNING) {
1974  errmsg = "Analysis already running!";
1975  goto errout;
1976  }
1977  else if (a->status == ASTATUS_DONE) {
1978  errmsg = "Analysis already done; cannot resume!";
1979  goto errout;
1980  }
1981 
1982  if (kill(monitor->p.pid,SIGCONT) < 0) {
1983  if (errno == ESRCH) {
1984  errmsg = "Analysis seems dead; cannot resume!";
1985  goto errout;
1986  }
1987  else {
1988  errmsg = "Error resuming analysis!";
1989  goto errout;
1990  }
1991  }
1993  }
1994 
1996 
1997  return SOAP_OK;
1998 
1999  errout:
2001 
2002  return soap_receiver_fault(soap,errmsg,errmsg);
2003 }
2004 
2005 int vmi1__CloseAnalysis(struct soap *soap,
2006  vmi1__AnalysisIdT aid,
2007  struct vmi1__NoneResponse *r) {
2008  struct analysis *a = NULL;
2009  struct monitor *monitor;
2010 
2012  (void **)&a,&monitor)) {
2013  return soap_receiver_fault(soap,"Nonexistent analysis!",
2014  "Specified analysis does not exist!");
2015  }
2016 
2017  /*
2018  * Let the monitor close/kill the analysis; if it supports external
2019  * control, pass the RPC to it and let it close itself in the child;
2020  * otherwise, close it from the outside.
2021  */
2022  if (a->desc->supports_external_control) {
2023  PROXY_REQUEST_LOCKED(soap,aid,&analysis_rpc_mutex);
2024 
2025  monitor_close_obj(monitor,a,0,0);
2026  }
2027  else
2028  monitor_close_obj(monitor,a,0,0);
2029 
2031 
2032  return SOAP_OK;
2033 }
2034 
2035 
2036 int vmi1__KillAnalysis(struct soap *soap,
2037  vmi1__AnalysisIdT aid,int kill_sig,
2038  struct vmi1__NoneResponse *r) {
2039  struct analysis *a = NULL;
2040  struct monitor *monitor;
2041 
2043  (void **)&a,&monitor)) {
2044  return soap_receiver_fault(soap,"Nonexistent analysis!",
2045  "Specified analysis does not exist!");
2046  }
2047 
2048  /*
2049  * Let the monitor close/kill the analysis; if it supports external
2050  * control, pass the RPC to it and let it close itself in the child;
2051  * otherwise, close it from the outside.
2052  */
2053 
2054  /*
2055  * Override whatever the default was!
2056  */
2057  if (kill_sig) {
2058  a->spec->kill_on_close = 1;
2059  a->spec->kill_on_close_sig = kill_sig;
2060  }
2061 
2062  if (a->desc->supports_external_control) {
2063  PROXY_REQUEST_LOCKED(soap,aid,&analysis_rpc_mutex);
2064 
2065  monitor_close_obj(monitor,a,0,0);
2066  }
2067  else
2068  monitor_close_obj(monitor,a,0,0);
2069 
2071 
2072  return SOAP_OK;
2073 }
2074 
2075 int vmi1__FinalizeAnalysis(struct soap *soap,
2076  vmi1__AnalysisIdT aid,
2077  struct vmi1__NoneResponse *r) {
2078  struct analysis *a = NULL;
2079  struct monitor *monitor;
2080 
2082  (void **)&a,&monitor)) {
2083  return soap_receiver_fault(soap,"Nonexistent analysis!",
2084  "Specified analysis does not exist!");
2085  }
2086 
2087  /*
2088  * Let the monitor close/kill the analysis; if it supports external
2089  * control, pass the RPC to it and let it close itself in the child;
2090  * otherwise, close it from the outside.
2091  */
2092 
2093  if (a->desc->supports_external_control) {
2094  PROXY_REQUEST_LOCKED(soap,aid,&analysis_rpc_mutex);
2095 
2096  monitor_del_obj(monitor,a);
2097  }
2098  else
2099  monitor_del_obj(monitor,a);
2100 
2102 
2103  return SOAP_OK;
2104 }
2105 
2106 int vmi1__GetAnalysis(struct soap *soap,
2107  vmi1__AnalysisIdT aid,
2108  struct vmi1__AnalysisResponse *r) {
2109  struct analysis *a = NULL;
2110  struct monitor *monitor;
2111  GHashTable *reftab;
2112 
2114  (void **)&a,&monitor)) {
2115  return soap_receiver_fault(soap,"Nonexistent analysis!",
2116  "Specified analysis does not exist!");
2117  }
2118 
2119  if (a->desc->supports_external_control) {
2120  PROXY_REQUEST_LOCKED(soap,aid,&analysis_rpc_mutex);
2121  }
2122  else {
2123  reftab = g_hash_table_new(g_direct_hash,g_direct_equal);
2124  r->analysis = a_analysis_to_x_AnalysisT(soap,a,reftab,NULL);
2125  g_hash_table_destroy(reftab);
2126  }
2127 
2129 
2130  return SOAP_OK;
2131 }
2132 
2133 int vmi1__GetAnalysisStatus(struct soap *soap,
2134  vmi1__AnalysisIdT aid,
2135  struct vmi1__AnalysisStatusResponse *r) {
2136  struct analysis *a = NULL;
2137  struct monitor *monitor;
2138  GHashTable *reftab;
2139 
2141  (void **)&a,&monitor)) {
2142  return soap_receiver_fault(soap,"Nonexistent analysis!",
2143  "Specified analysis does not exist!");
2144  }
2145 
2146  reftab = g_hash_table_new(g_direct_hash,g_direct_equal);
2147  r->analysisStatus =
2148  a_analysis_status_t_to_x_AnalysisStatusT(soap,a->status,reftab,NULL);
2149  g_hash_table_destroy(reftab);
2150 
2152 
2153  return SOAP_OK;
2154 }
2155 
2156 int vmi1__GetAnalysisResults(struct soap *soap,
2157  vmi1__AnalysisIdT aid,
2158  struct vmi1__AnalysisResultsResponse *r) {
2159  struct analysis *a = NULL;
2160  struct monitor *monitor;
2161  GHashTable *reftab;
2162 
2164  (void **)&a,&monitor)) {
2165  return soap_receiver_fault(soap,"Nonexistent analysis!",
2166  "Specified analysis does not exist!");
2167  }
2168 
2169  reftab = g_hash_table_new(g_direct_hash,g_direct_equal);
2171  &r->analysisResults);
2172  g_hash_table_destroy(reftab);
2173 
2175 
2176  return SOAP_OK;
2177 }
2178 
2179 int vmi1__GetAnalysisLogs(struct soap *soap,
2180  vmi1__AnalysisIdT aid,int maxSize,
2181  struct vmi1__AnalysisLogsResponse *r) {
2182  struct analysis *a = NULL;
2183  struct monitor *m = NULL;
2184 
2186  (void **)&a,&m)) {
2187  return soap_receiver_fault(soap,"Nonexistent analysis!",
2188  "Specified analysis does not exist!");
2189  }
2190 
2192  PROXY_REQUEST_LOCKED(soap,aid,&analysis_rpc_mutex);
2193 
2194  if (a->spec->outfile)
2195  r->stdoutLog =
2197  if (a->spec->errfile)
2198  r->stderrLog =
2200  if (a->target_spec) {
2201  if (a->target_spec->outfile)
2202  r->targetStdoutLog =
2204  a->target_spec->outfile,
2205  maxSize);
2206  if (a->target_spec->errfile)
2207  r->targetStderrLog =
2209  a->target_spec->errfile,
2210  maxSize);
2211  }
2212 
2214 
2215  return SOAP_OK;
2216 }
2217 
2218 int vmi1__AnalysisBindListener(struct soap *soap,
2219  vmi1__AnalysisIdT aid,vmi1__ListenerT *listener,
2220  struct vmi1__NoneResponse *r) {
2221  char *url;
2222  int len = 0;
2223  struct analysis *a = NULL;
2224 
2225  if (!listener)
2226  return soap_receiver_fault(soap,"Bad listener!","Bad listener!");
2227  else if (listener->url != NULL)
2228  url = listener->url;
2229  else if (listener->hostname != NULL && listener->port != NULL) {
2230  len = sizeof("http://") + strlen(listener->hostname) \
2231  + sizeof(":") + 11 + sizeof(":/vmi/1/targetListener") + 1;
2232  url = malloc(len * sizeof(char));
2233  sprintf(url,"http://%s:%d/vmi/1/targetListener",
2234  listener->hostname,*listener->port);
2235  }
2236  else {
2237  return soap_receiver_fault(soap,"Bad listener!","Bad listener!");
2238  }
2239 
2240  /*
2241  * We want to "snoop" on this listener call -- saving the listener
2242  * in the server so that the thread monitoring stdout/err has it if
2243  * it needs to autoparse results. Plus, if the analysis doesn't
2244  * support external control, this is the only place to stand.
2245  */
2246 
2248  (void **)&a,NULL)) {
2249  if (len)
2250  free(url);
2251  return soap_receiver_fault(soap,"Nonexistent analysis!",
2252  "Specified analysis does not exist!");
2253  }
2254 
2255  /* XXX: this check is pretty bad; it should be monitor_is_parent() */
2256  if (!a->target) {
2258  if (len)
2259  free(url);
2260  return soap_receiver_fault(soap,
2261  "Could not bind to analysis (monitor)!",
2262  "Could not bind to analysis (monitor)!");
2263  }
2264  }
2265 
2266  if (a->desc->supports_external_control) {
2267  PROXY_REQUEST_LOCKED(soap,aid,&analysis_rpc_mutex);
2268 
2270  if (len)
2271  free(url);
2272  return soap_receiver_fault(soap,"Could not bind to analysis!",
2273  "Could not bind to analysis!");
2274  }
2275  }
2276 
2278 
2279  return SOAP_OK;
2280 }
2281 
2282 int vmi1__AnalysisUnbindListener(struct soap *soap,
2283  vmi1__AnalysisIdT aid,vmi1__ListenerT *listener,
2284  struct vmi1__NoneResponse *r) {
2285  char *url;
2286  int len = 0;
2287  struct analysis *a = NULL;
2288 
2289  if (!listener)
2290  return soap_receiver_fault(soap,"Bad listener!","Bad listener!");
2291  else if (listener->url != NULL)
2292  url = listener->url;
2293  else if (listener->hostname != NULL && listener->port != NULL) {
2294  len = sizeof("http://") + strlen(listener->hostname) \
2295  + sizeof(":") + 11 + sizeof(":/vmi/1/targetListener") + 1;
2296  url = malloc(len * sizeof(char));
2297  sprintf(url,"http://%s:%d/vmi/1/targetListener",
2298  listener->hostname,*listener->port);
2299  }
2300  else {
2301  return soap_receiver_fault(soap,"Bad listener!","Bad listener!");
2302  }
2303 
2304  /*
2305  * We want to "snoop" on this listener call -- saving the listener
2306  * in the server so that the thread monitoring stdout/err has it if
2307  * it needs to autoparse results. Plus, if the analysis doesn't
2308  * support external control, this is the only place to stand.
2309  */
2310 
2312  (void **)&a,NULL)) {
2313  if (len)
2314  free(url);
2315  return soap_receiver_fault(soap,"Nonexistent analysis!",
2316  "Specified analysis does not exist!");
2317  }
2318 
2319  /* XXX: this check is pretty bad; it should be monitor_is_parent() */
2320  if (!a->target) {
2322  if (len)
2323  free(url);
2324  return soap_receiver_fault(soap,
2325  "Could not bind to analysis (monitor)!",
2326  "Could not bind to analysis (monitor)!");
2327  }
2328  }
2329 
2330  if (a->desc->supports_external_control) {
2331  PROXY_REQUEST_LOCKED(soap,aid,&analysis_rpc_mutex);
2332 
2334  if (len)
2335  free(url);
2336  return soap_receiver_fault(soap,"Could not bind to analysis!",
2337  "Could not bind to analysis!");
2338  }
2339  }
2340 
2342 
2343  return SOAP_OK;
2344 }
2345 
2349 static int analysis_rpc_monitor_evloop_attach(struct evloop *evloop,void *obj) {
2350  if (!obj)
2351  return 0;
2352 
2353  if (((struct analysis *)obj)->target)
2354  return analysis_attach_evloop((struct analysis *)obj,evloop);
2355  else
2356  return 0;
2357 }
2358 
2359 static int analysis_rpc_monitor_evloop_detach(struct evloop *evloop,void *obj) {
2360  if (!obj)
2361  return 0;
2362 
2363  if (((struct analysis *)obj)->target)
2364  return analysis_detach_evloop((struct analysis *)obj);
2365  else
2366  return 0;
2367 }
2368 
2369 static int analysis_rpc_monitor_close(struct monitor *monitor,
2370  void *obj,void *objstate,
2371  int dokill,int kill_sig) {
2372  struct analysis *analysis = (struct analysis *)obj;
2373  int retval;
2374  int rsig = kill_sig;
2375  int apid = monitor->p.pid;
2376 
2377  if (!obj)
2378  return 0;
2379 
2380  if (analysis->target)
2381  target_close(analysis->target);
2382  else if (dokill || analysis->spec->kill_on_close) {
2383  if (!dokill)
2384  rsig = analysis->spec->kill_on_close_sig;
2385  vdebug(5,LA_XML,LF_XML,
2386  "killing analysis pgid %d with signal %d\n",apid,rsig);
2387  if (kill(-apid,rsig) < 0) {
2388  vwarn("kill(%d,%d): %s\n",apid,rsig,strerror(errno));
2389  }
2390  }
2391 
2392  if ((retval = analysis_close(analysis)) != ASTATUS_DONE) {
2393  verror("could not close analysis %d (error %d)!\n",analysis->id,retval);
2394  }
2395 
2396  return 0;
2397 }
2398 
2399 static int analysis_rpc_monitor_fini(struct monitor *monitor,
2400  void *obj,void *objstate) {
2401  struct analysis *analysis = (struct analysis *)obj;
2402  if (!obj)
2403  return 0;
2404  if (analysis->target_spec) {
2405  target_free_spec(analysis->target_spec);
2406  analysis->target_spec = NULL;
2407  }
2408  else if (analysis->target && analysis->target->spec) {
2409  target_free_spec(analysis->target->spec);
2410  analysis->target->spec = NULL;
2411  }
2412  analysis_free(analysis);
2413  return 0;
2414 }
2415 
2416 static int analysis_rpc_monitor_evloop_is_attached(struct evloop *evloop,
2417  void *obj) {
2418  if (!obj)
2419  return 0;
2420  return analysis_is_evloop_attached((struct analysis *)obj,evloop);
2421 }
2422 
2423 static int analysis_rpc_monitor_error(monitor_error_t error,void *obj) {
2424  vdebug(5,LA_XML,LF_RPC,"analysis id %d (error %d)\n",
2425  ((struct analysis *)obj)->id,error);
2426  return 0;
2427 }
2428 
2429 static int analysis_rpc_monitor_fatal_error(monitor_error_t error,void *obj) {
2430  vdebug(5,LA_XML,LF_RPC,"analysis id %d (error %d)\n",
2431  ((struct analysis *)obj)->id,error);
2432  return 0;
2433 }
2434 
2436  GHashTable *reftab;
2437  struct vmi1__AnalysisEventT event;
2440 };
2441 
2442 static int _analysis_rpc_notify_listener_event(struct generic_rpc_listener *l,
2443  int is_owner,void *data) {
2444  result_t retval;
2445  struct analysis_rpc_listener_event_data *d = \
2446  (struct analysis_rpc_listener_event_data *)data;
2447  int rc;
2448 
2449  rc = soap_call_vmi1__AnalysisEventNotification(&l->soap,l->url,NULL,
2450  &d->event,&d->r);
2451  if (rc != SOAP_OK) {
2452  if (l->soap.error == SOAP_EOF && l->soap.errnum == 0) {
2453  vwarn("timeout notifying %s; removing!",l->url);
2454  }
2455  else {
2456  verrorc("AnalysisEvent client call failure %s : ",
2457  l->url);
2458  soap_print_fault(&l->soap,stderr);
2459  }
2460  /* Let generic_rpc do this... */
2461  //soap_closesock(&lad->soap);
2462  return -1;
2463  }
2464 
2465  retval = x_ResultT_to_t_result_t(&l->soap,d->r.result);
2466  if (is_owner) {
2467  //if (retval > lad->retval)
2468  d->retval = retval;
2469 
2470  vdebug(5,LA_XML,LF_RPC,
2471  "notified authoritative listener %s (which returned %d)\n",
2472  l->url,retval);
2473  }
2474  else {
2475  vdebug(5,LA_XML,LF_RPC,
2476  "notified non-authoritative listener %s (which returned %d)\n",
2477  l->url,retval);
2478  }
2479 
2480  if (!l->soap.keep_alive)
2481  soap_closesock(&l->soap);
2482  /*
2483  * Clean up temp/serialization data, but don't kill the sock if we
2484  * can avoid it.
2485  */
2486  soap_destroy(&l->soap);
2487  soap_end(&l->soap);
2488  //soap_done(&l->soap);
2489 
2490  return 0;
2491 }
2492 
2493 int analysis_rpc_notify_listeners_event(struct analysis *analysis,
2494  enum _vmi1__analysisEventType type) {
2495  struct soap encoder;
2497 
2498  memset(&d,0,sizeof(d));
2499 
2500  /*
2501  * We only want to build the gsoap data struct once -- so we have to
2502  * set up a temp soap struct to do that on. We can't use the
2503  * per-listener soap struct yet cause we don't have it until we're
2504  * in the iterator above.
2505  */
2506  soap_init(&encoder);
2507  d.reftab = g_hash_table_new_full(g_direct_hash,g_direct_equal,NULL,NULL);
2508  d.retval = RESULT_SUCCESS;
2509  d.event.analysisEventType = type;
2510  d.event.analysisId = analysis->id;
2512  d.reftab,&d.event.analysisStatus);
2513 
2515  _analysis_rpc_notify_listener_event,&d);
2516  /*
2517  * Clean up temp/serialization data, but don't kill the sock if we
2518  * can avoid it.
2519  */
2520  g_hash_table_destroy(d.reftab);
2521  soap_destroy(&encoder);
2522  soap_end(&encoder);
2523  soap_done(&encoder);
2524 
2525  return 0;
2526 }
2527 
2528 static int analysis_rpc_monitor_event(struct monitor *monitor,
2530  int objid,void *obj) {
2531  struct analysis *a = (struct analysis *)obj;
2532 
2533  vdebug(5,LA_XML,LF_RPC,"analysis id %d (event %d)\n",
2534  a->id,event);
2535 
2536  if (event != MONITOR_EVENT_CHILD_DIED)
2537  return 0;
2538 
2539  /*
2540  * Send notification.
2541  */
2542  analysis_rpc_notify_listeners_event(a,_vmi1__analysisEventType__exited);
2543 
2544  return 0;
2545 }
2546 
2547 static int analysis_rpc_monitor_child_recv_msg(struct monitor *monitor,
2548  struct monitor_msg *msg) {
2549  struct analysis *analysis = (struct analysis *)monitor->obj;
2550 
2551  vdebug(9,LA_XML,LF_RPC,"msg(%d:%hd,%hd,%d) = '%s' (analysis %d (%p))\n",
2552  msg->id,msg->cmd,msg->seqno,msg->len,msg->msg,msg->objid,analysis);
2553 
2554  return proxyreq_recv_request(monitor,msg);
2555 }
2556 
2557 static int analysis_rpc_monitor_recv_msg(struct monitor *monitor,
2558  struct monitor_msg *msg) {
2559  struct analysis *analysis = (struct analysis *)monitor->obj;
2560 
2561  vdebug(9,LA_XML,LF_RPC,"msg(%d:%hd,%hd,%d) = '%s' (analysis %d (%p))\n",
2562  msg->id,msg->cmd,msg->seqno,msg->len,msg->msg,msg->objid,analysis);
2563 
2564  return proxyreq_recv_response(monitor,msg);
2565 }
void target_rpc_fini(void)
Definition: target_rpc.c:416
int monitor_del_objid(struct monitor *monitor, int objid)
Definition: monitor.c:788
struct vmi1__AnalysisEventT event
struct vmi1__DebugFileOptsT defDebugFileOpts
Definition: debuginfo_rpc.c:45
int analysis_rpc_handle_request(struct soap *soap)
Definition: analysis_rpc.c:159
struct xsd__hexBinary * stderrLog
int proxyreq_recv_request(struct monitor *monitor, struct monitor_msg *msg)
Definition: proxyreq.c:552
int vmi1__UploadAnalysis(struct soap *soap, struct vmi1__AnalysisDescT *analysisDesc, struct xsd__hexBinary *inputFileContents, struct vmi1__NoneResponse *r)
Definition: analysis_rpc.c:715
char * errfile
Definition: analysis.h:313
int vmi1__ResumeAnalysis(struct soap *soap, vmi1__AnalysisIdT aid, struct vmi1__NoneResponse *r)
struct target_spec * target_spec
Definition: analysis.h:241
struct vmi1__AnalysisResultT * a_analysis_datum_to_x_AnalysisResultT(struct soap *soap, struct analysis_datum *in, struct analysis *analysis, GHashTable *reftab, struct vmi1__AnalysisResultT *out)
Definition: analysis_xml.c:338
struct monitor_objtype_ops analysis_rpc_monitor_objtype_ops
Definition: analysis_rpc.c:70
void * obj
Definition: monitor.h:244
int monitor_lookup_objid_lock_objtype(int objid, int objtype, void **obj, struct monitor **monitor)
Definition: monitor.c:350
int analysis_rpc_notify_listeners_event(struct analysis *analysis, enum _vmi1__analysisEventType type)
void analysis_spec_free(struct analysis_spec *spec)
Definition: analysis.c:630
char * binary
Definition: analysis.h:261
int pid
Definition: monitor.h:294
int analysis_rpc_stdout_callback(int fd, char *buf, int len, void *state)
Definition: analysis_rpc.c:260
int stdout_buf_len
Definition: analysis.h:246
struct vmi1__AnalysisDescT * a_analysis_desc_to_x_AnalysisDescT(struct soap *soap, struct analysis_desc *in, GHashTable *reftab, struct vmi1__AnalysisDescT *out)
Definition: analysis_xml.c:112
GHashTable * in_params_long
Definition: analysis.h:278
struct vmi1__AnalysisResultNotificationResponse r
Definition: analysis_rpc.c:166
#define SOAP_CALLOC(soap, nmemb, size)
Definition: util.h:25
int monitor_register_objtype(int objtype, struct monitor_objtype_ops *ops, pthread_mutex_t *objtype_mutex)
Definition: monitor.c:1052
int analysis_detach_evloop(struct analysis *analysis)
Definition: analysis.c:381
int analysis_datum_add_simple_value(struct analysis_datum *datum, char *name, char *value, int no_copy)
Definition: analysis.c:436
int generic_rpc_unbind_dynlistener_objid(rpc_svctype_t svctype, char *listener_url, int objid)
Definition: generic_rpc.c:864
struct array_list * results
Definition: analysis.h:248
enum vmi1__AnalysisStatusT analysisStatus
int monitor_get_unique_objid(void)
Definition: monitor.c:161
static uint64_t unsigned int i
struct target_spec * overlay_target_spec
Definition: analysis.h:242
int objid
Definition: monitor.h:335
struct monitor * monitor
char * msg
Definition: monitor.h:352
void generic_rpc_init(void)
Definition: generic_rpc.c:69
int vmi1__PauseAnalysis(struct soap *soap, vmi1__AnalysisIdT aid, struct vmi1__NoneResponse *r)
char * path
int vmi1__AnalysisUnbindListener(struct soap *soap, vmi1__AnalysisIdT aid, vmi1__ListenerT *listener, struct vmi1__NoneResponse *r)
struct vmi1__AnalysisResultsT analysisResults
struct vmi1__AnalysisT * a_analysis_to_x_AnalysisT(struct soap *soap, struct analysis *in, GHashTable *reftab, struct vmi1__AnalysisT *out)
Definition: analysis_xml.c:24
int generic_rpc_unbind_all_listeners_objid(rpc_svctype_t svctype, int objid)
Definition: generic_rpc.c:733
int monitor_setup_stderr(struct monitor *monitor, int maxbufsiz, char *stderr_logfile, monitor_stdio_callback_t stderr_callback, void *callback_state)
Definition: monitor.c:1897
struct vmi1__AnalysisResultsT * a_analysis_datum_list_to_x_AnalysisResultsT(struct soap *soap, struct array_list *in, struct analysis *analysis, GHashTable *reftab, struct vmi1__AnalysisResultsT *out)
Definition: analysis_xml.c:445
struct analysis * analysis_create(int id, struct analysis_spec *spec, struct analysis_desc *desc, int target_id, struct target *target)
Definition: analysis.c:390
int analysis_id
Definition: analysis.h:291
struct target ** ots
Definition: dumptarget.c:50
char * tmpdir
Definition: analysis.h:216
void analysis_rpc_fini(void)
Definition: analysis_rpc.c:110
int target_close(struct target *target)
Definition: target_api.c:1511
struct vmi1__AnalysisResultT result
Definition: analysis_rpc.c:165
#define verror(format,...)
Definition: log.h:30
int vmi1__InstantiateAnalysis(struct soap *soap, struct vmi1__AnalysisSpecT *analysisSpec, struct vmi1__TargetSpecT *targetSpec, struct vmi1__ListenerT *ownerListener, struct vmi1__AnalysisResponse *r)
Definition: analysis_rpc.c:722
#define verrorc(format,...)
Definition: log.h:32
void ** list
Definition: alist.h:34
int analysis_attach_evloop(struct analysis *analysis, struct evloop *evloop)
Definition: analysis.c:377
Definition: evloop.h:66
struct analysis_desc * desc
Definition: analysis.h:219
char * outfile
Definition: analysis.h:312
int vmi1__GetAnalysisStatus(struct soap *soap, vmi1__AnalysisIdT aid, struct vmi1__AnalysisStatusResponse *r)
void target_rpc_init(void)
Definition: target_rpc.c:393
int proxyreq_attach_new_objid(struct proxyreq *pr, int objid, struct monitor *monitor)
Definition: proxyreq.c:421
struct xsd__hexBinary * targetStdoutLog
int vmi1__InstantiateOverlayAnalysisByThreadName(struct soap *soap, struct vmi1__AnalysisSpecT *analysisSpec, struct vmi1__TargetSpecT *targetSpec, struct vmi1__TargetSpecT *overlayTargetSpec, char *baseThreadName, vmi1__ListenerT *ownerListener, struct vmi1__AnalysisResponse *r)
#define vwarn(format,...)
Definition: log.h:33
result_t x_ResultT_to_t_result_t(struct soap *soap, enum vmi1__ResultT in)
Definition: common_xml.c:24
void free(void *ptr)
Definition: debugserver.c:207
struct target_spec * x_TargetSpecT_to_t_target_spec(struct soap *soap, struct vmi1__TargetSpecT *spec, GHashTable *reftab, struct target_spec *out)
Definition: target_xml.c:206
struct target * target
Definition: analysis.h:234
int vmi1__GetAnalysis(struct soap *soap, vmi1__AnalysisIdT aid, struct vmi1__AnalysisResponse *r)
int monitor_lock_objtype(int objtype)
Definition: monitor.c:243
struct vmi1__AnalysisDescT * analysisDesc
struct xsd__hexBinary * stdoutLog
void analysis_set_status(struct analysis *analysis, analysis_status_t status)
Definition: analysis.c:521
#define array_list_foreach(alist, lpc, placeholder)
Definition: alist.h:371
analysis_status_t status
Definition: analysis.h:221
struct soap soap
Definition: generic_rpc.h:97
int vmi1__FinalizeAnalysis(struct soap *soap, vmi1__AnalysisIdT aid, struct vmi1__NoneResponse *r)
int id
Definition: analysis.h:214
monitor_event_t
Definition: monitor.h:62
struct analysis_spec * spec
Definition: analysis.h:218
struct analysis_datum * analysis_create_simple_datum(struct analysis *analysis, int id, char *name, int type, char *value, char *msg, int no_copy)
Definition: analysis.c:407
char * analysis_find(const char *name)
Definition: analysis.c:150
uint32_t supports_external_control
Definition: analysis.h:263
struct analysis_spec * x_AnalysisSpecT_to_a_analysis_spec(struct soap *soap, struct vmi1__AnalysisSpecT *in, GHashTable *reftab, struct analysis_spec *out)
Definition: analysis_xml.c:191
short cmd
Definition: monitor.h:349
void target_free_spec(struct target_spec *spec)
Definition: target_api.c:453
int target_spec_to_argv(struct target_spec *spec, char *arg0, int *argc, char ***argv)
Definition: target.c:416
int monitor_close_obj(struct monitor *monitor, void *obj, int kill, int kill_sig)
Definition: monitor.c:622
int monitor_del_obj(struct monitor *monitor, void *obj)
Definition: monitor.c:763
Definition: log.h:203
int monitor_unlock_objtype_unsafe(int objtype)
Definition: monitor.c:275
#define MONITOR_OBJTYPE_ANALYSIS
Definition: analysis_rpc.h:27
void monitor_fini(void)
Definition: monitor.c:127
analysis_status_t analysis_close(struct analysis *analysis)
Definition: analysis.c:527
int stdout_buf_alen
Definition: analysis.h:245
int __vmi1__InstantiateOverlayAnalysis(struct soap *soap, struct vmi1__AnalysisSpecT *analysisSpec, struct vmi1__TargetSpecT *targetSpec, struct vmi1__TargetSpecT *overlayTargetSpec, vmi1__ThreadIdT baseThid, char *baseThreadName, vmi1__ListenerT *ownerListener, struct vmi1__AnalysisResponse *r)
void analysis_init(void)
Definition: analysis.c:67
int analysis_is_evloop_attached(struct analysis *analysis, struct evloop *evloop)
Definition: analysis.c:385
int analysis_rpc_notify_listeners_result(struct analysis *analysis, struct analysis_datum *datum)
Definition: analysis_rpc.c:225
struct xsd__hexBinary * generic_rpc_read_file_into_hexBinary(struct soap *soap, char *filename, int max_size)
Definition: generic_rpc.c:981
enum vmi1__AnalysisStatusT a_analysis_status_t_to_x_AnalysisStatusT(struct soap *soap, analysis_status_t status, GHashTable *reftab, enum vmi1__AnalysisStatusT *out)
Definition: analysis_xml.c:609
int len
Definition: dumptarget.c:52
void analysis_fini(void)
Definition: analysis.c:81
int kill_on_close_sig
Definition: analysis.h:306
void generic_rpc_register_svctype(rpc_svctype_t svctype)
Definition: generic_rpc.c:139
int monitor_setup_stdin(struct monitor *monitor, char *stdin_buf, int stdin_buflen)
Definition: monitor.c:1817
char * long_name
Definition: analysis.h:320
int generic_rpc_bind_dynlistener_objid(rpc_svctype_t svctype, char *listener_url, int objid, int owns)
Definition: generic_rpc.c:804
char * stdout_buf
Definition: analysis.h:244
int vmi1__KillAnalysis(struct soap *soap, vmi1__AnalysisIdT aid, int kill_sig, struct vmi1__NoneResponse *r)
#define vdebug(devel, areas, flags, format,...)
Definition: log.h:302
uint32_t kill_on_close
Definition: analysis.h:296
void * realloc(void *ptr, size_t size)
Definition: debugserver.c:221
short seqno
Definition: monitor.h:350
int vmi1__ListAnalysisDescNames(struct soap *soap, void *_, struct vmi1__AnalysisDescNamesResponse *r)
Definition: analysis_rpc.c:629
uint32_t supports_autoparse_simple_results
Definition: analysis.h:263
void analysis_datum_free(struct analysis_datum *datum)
Definition: analysis.c:479
Definition: log.h:72
struct monitor::@11 p
void * calloc(size_t nmemb, size_t size)
Definition: debugserver.c:200
struct array_list * monitor_list_objids_by_objtype_lock_objtype(int objtype, int include_null)
Definition: monitor.c:279
uint8_t is_command_line_switched
Definition: analysis.h:317
char * name
Definition: analysis.h:319
result_t
Definition: common.h:25
struct xsd__hexBinary * targetStderrLog
struct array_list * monitor_list_objs_by_objtype_lock_objtype(int objtype, int include_null)
Definition: monitor.c:315
struct vmi1__AnalysisT * analysis
struct vmi1__AnalysisT * analysis
int monitor_setup_stdout(struct monitor *monitor, int maxbufsiz, char *stdout_logfile, monitor_stdio_callback_t stdout_callback, void *callback_state)
Definition: monitor.c:1847
void generic_rpc_fini(void)
Definition: generic_rpc.c:104
void analysis_desc_free(struct analysis_desc *desc)
Definition: analysis.c:594
struct array_list * analysis_load_all(void)
Definition: analysis.c:331
void analysis_rpc_init(void)
Definition: analysis_rpc.c:86
struct analysis_desc * analysis_load_pathname(const char *path)
Definition: analysis.c:269
struct vmi1__AnalysisEventNotificationResponse r
struct array_list * analysis_list_names(void)
Definition: analysis.c:90
int proxyreq_handle_request(struct soap *soap, char *svc_name)
Definition: proxyreq.c:30
int vmi1__CloseAnalysis(struct soap *soap, vmi1__AnalysisIdT aid, struct vmi1__NoneResponse *r)
char * infile
Definition: target_api.h:2286
int generic_rpc_listener_notify_all(rpc_svctype_t svctype, int objid, generic_rpc_listener_notifier_t *notifier, void *data)
Definition: generic_rpc.c:902
void analysis_free(struct analysis *analysis)
Definition: analysis.c:564
int(* evloop_attach)(struct evloop *evloop, void *obj)
Definition: monitor.h:93
int monitor_lookup_objid(int objid, int *objtype, void **obj, struct monitor **monitor)
Definition: monitor.c:219
int proxyreq_recv_response(struct monitor *monitor, struct monitor_msg *msg)
Definition: proxyreq.c:621
void monitor_init(void)
Definition: monitor.c:93
uint8_t is_command_line
Definition: analysis.h:317
Definition: log.h:202
struct target_spec * spec
Definition: target_api.h:2605
int vmi1__ListAnalysisDescs(struct soap *soap, void *_, struct vmi1__AnalysisDescsResponse *r)
Definition: analysis_rpc.c:654
int vmi1__GetAnalysisLogs(struct soap *soap, vmi1__AnalysisIdT aid, int maxSize, struct vmi1__AnalysisLogsResponse *r)
int analysis_rpc_stderr_callback(int fd, char *buf, int len, void *state)
Definition: analysis_rpc.c:619
GHashTable * in_params
Definition: analysis.h:277
void * malloc(size_t size)
Definition: debugserver.c:214
char * ANALYSIS_TMPDIR
Definition: analysis.c:55
void generic_rpc_unregister_svctype(rpc_svctype_t svctype)
Definition: generic_rpc.c:195
char * errfile
Definition: target_api.h:2288
#define SOAP_STRCPY(soap, d, s)
Definition: util.h:28
#define PROXY_REQUEST_LOCKED(soap, mobjid, mutex)
Definition: proxyreq.h:288
char * outfile
Definition: target_api.h:2287
#define _CB_SAVEBUF_INC
Definition: analysis_rpc.c:258
int generic_rpc_count_listeners(rpc_svctype_t svctype, int objid)
Definition: generic_rpc.c:880
int monitor_spawn(struct monitor *monitor, char *filename, char *const argv[], char *const envp[], char *dir)
Definition: monitor.c:2002
int vmi1__AnalysisBindListener(struct soap *soap, vmi1__AnalysisIdT aid, vmi1__ListenerT *listener, struct vmi1__NoneResponse *r)
struct array_list * in_params
Definition: analysis.h:309
char * name
Definition: analysis.h:289
int vmi1__GetAnalysisResults(struct soap *soap, vmi1__AnalysisIdT aid, struct vmi1__AnalysisResultsResponse *r)
struct monitor * monitor_create(monitor_type_t type, monitor_flags_t flags, int objid, int objtype, void *obj, void *objstate)
Definition: monitor.c:1594
int vmi1__ListAnalyses(struct soap *soap, void *_, struct vmi1__AnalysesResponse *r)
Definition: analysis_rpc.c:684
monitor_error_t
Definition: monitor.h:54
int vmi1__InstantiateOverlayAnalysis(struct soap *soap, struct vmi1__AnalysisSpecT *analysisSpec, struct vmi1__TargetSpecT *targetSpec, struct vmi1__TargetSpecT *overlayTargetSpec, vmi1__ThreadIdT baseThid, vmi1__ListenerT *ownerListener, struct vmi1__AnalysisResponse *r)