snort  2.9.17.1
About: Snort is a network intrusion prevention and detection system (IDS/IPS) combining the benefits of signature, protocol and anomaly-based inspection.
  Fossies Dox: snort-2.9.17.1.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

service_rpc.c
Go to the documentation of this file.
1 /*
2 ** Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved.
3 ** Copyright (C) 2005-2013 Sourcefire, Inc.
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License Version 2 as
7 ** published by the Free Software Foundation. You may not use, modify or
8 ** distribute this program under any other version of the GNU General
9 ** Public License.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20 
21 
22 #include <ctype.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <stddef.h>
26 #include <sys/types.h>
27 #include <netinet/in.h>
28 #include <netdb.h>
29 
30 #include "appIdApi.h"
31 #include "appInfoTable.h"
32 #include "flow.h"
33 #include "service_api.h"
34 
35 #if defined(FREEBSD) || defined(OPENBSD)
36 #include "rpc/rpc.h"
37 #endif
38 
39 /*#define RNA_DEBUG_RPC 1 */
40 
41 typedef enum
42 {
47 
48 typedef enum
49 {
60 
61 typedef enum
62 {
67 
68 #define min(x,y) ((x)<(y) ? (x):(y))
69 
70 #define RPC_TYPE_CALL 0
71 #define RPC_TYPE_REPLY 1
72 
73 #define RPC_PROGRAM_PORTMAP 100000
74 #define RPC_PORTMAP_GETPORT 3
75 
76 #define RPC_REPLY_ACCEPTED 0
77 #define RPC_REPLY_DENIED 1
78 
79 #define RPC_MAX_ACCEPTED 4
80 #define RPC_MAX_DENIED 5
81 
82 #define RPC_TCP_FRAG_MASK 0x80000000
83 
84 /* sizeof(ServiceRPCCall)+sizeof(_SERVICE_RPC_PORTMAP)==56 */
85 #define RPC_MAX_TCP_PACKET_SIZE 56
86 
87 #pragma pack(1)
88 
89 typedef struct _SERVICE_RPC_FRAG
90 {
93 
94 typedef struct _SERVICE_RPC_AUTH
95 {
99 
100 typedef struct _SERVICE_RPC_PORTMAP
101 {
107 
109 {
112 
113 typedef struct _SERVICE_RPC_HEADER
114 {
118 
120 {
129 
131 {
137 
138 #pragma pack()
139 
140 typedef struct _SERVICE_RPC_DATA
141 {
154  int once;
156 
157 static int rpc_init(const InitServiceAPI * const init_api);
158 static int rpc_validate(ServiceValidationArgs* args);
159 static int rpc_tcp_validate(ServiceValidationArgs* args);
160 static void rpc_clean(const CleanServiceAPI * const clean_api);
161 
163 {
164  .next = NULL,
165  .validate = &rpc_validate,
166  .detectorType = DETECTOR_TYPE_DECODER,
167  .name = "rpc",
168  .ref_count = 1,
169  .current_ref_count = 1,
170 };
172 {
173  .next = NULL,
174  .validate = &rpc_tcp_validate,
175  .detectorType = DETECTOR_TYPE_DECODER,
176  .name = "tcp rpc",
177  .ref_count = 1,
178  .current_ref_count = 1,
179 };
180 
181 #define RPC_PORT_PORTMAPPER 111
182 #define RPC_PORT_NFS 2049
183 #define RPC_PORT_MOUNTD 4046
184 #define RPC_PORT_NLOCKMGR 4045
185 
187 {
188  {&rpc_validate, RPC_PORT_PORTMAPPER, IPPROTO_UDP},
189  {&rpc_validate, RPC_PORT_PORTMAPPER, IPPROTO_UDP, 1},
190  {&rpc_tcp_validate, RPC_PORT_PORTMAPPER, IPPROTO_TCP},
191  {&rpc_validate, RPC_PORT_NFS, IPPROTO_UDP},
192  {&rpc_validate, RPC_PORT_NFS, IPPROTO_UDP, 1},
193  {&rpc_tcp_validate, RPC_PORT_NFS, IPPROTO_TCP},
194  {&rpc_validate, RPC_PORT_MOUNTD, IPPROTO_UDP},
195  {&rpc_validate, RPC_PORT_MOUNTD, IPPROTO_UDP, 1},
196  {&rpc_tcp_validate, RPC_PORT_MOUNTD, IPPROTO_TCP},
197  {&rpc_validate, RPC_PORT_NLOCKMGR, IPPROTO_UDP},
198  {&rpc_validate, RPC_PORT_NLOCKMGR, IPPROTO_UDP, 1},
199  {&rpc_tcp_validate, RPC_PORT_NLOCKMGR, IPPROTO_TCP},
200  {NULL, 0, 0}
201 };
202 
204 {
205  "RPC",
206  &rpc_init,
207  pp,
208  .clean = rpc_clean
209 };
210 
211 typedef struct _RPC_PROGRAM
212 {
215  char *name;
217 
219 
220 static uint8_t rpc_reply_accepted_pattern[8] = {0,0,0,1,0,0,0,0};
221 static uint8_t rpc_reply_denied_pattern[8] = {0,0,0,1,0,0,0,1};
222 
224 {
226 };
227 
228 static int16_t app_id = 0;
229 
230 static int rpc_init(const InitServiceAPI * const init_api)
231 {
232  struct rpcent *rpc;
233  RPCProgram *prog;
234 
235 #ifdef TARGET_BASED
236  app_id = init_api->dpd->addProtocolReference("sunrpc");
237 #endif
238 
239  if (!rpc_programs)
240  {
241  while ((rpc = getrpcent()))
242  {
243  if (rpc->r_name)
244  {
245  prog = calloc(1, sizeof(RPCProgram));
246  if (prog)
247  {
248  prog->program = rpc->r_number;
249  prog->next = rpc_programs;
250  rpc_programs = prog;
251  prog->name = strdup(rpc->r_name);
252  if (!prog->name)
253  _dpd.errMsg("failed to allocate rpc program name");
254  }
255  }
256  }
257  endrpcent();
258  }
259 
261  sizeof(rpc_reply_accepted_pattern), 8, "rpc", init_api->pAppidConfig);
263  sizeof(rpc_reply_denied_pattern), 8, "rpc", init_api->pAppidConfig);
265  sizeof(rpc_reply_accepted_pattern), 4, "rpc", init_api->pAppidConfig);
266  init_api->RegisterPattern(&rpc_validate, IPPROTO_UDP, rpc_reply_denied_pattern,
267  sizeof(rpc_reply_denied_pattern), 4, "rpc", init_api->pAppidConfig);
268 
269  unsigned i;
270  for (i=0; i < sizeof(appIdRegistry)/sizeof(*appIdRegistry); i++)
271  {
272  _dpd.debugMsg(DEBUG_LOG,"registering appId: %d\n",appIdRegistry[i].appId);
273  init_api->RegisterAppId(&rpc_validate, appIdRegistry[i].appId, appIdRegistry[i].additionalInfo, init_api->pAppidConfig);
274  }
275 
276  return 0;
277 }
278 
279 static const RPCProgram *FindRPCProgram(uint32_t program)
280 {
281  RPCProgram *rpc;
282 
283  for (rpc=rpc_programs; rpc; rpc=rpc->next)
284  {
285  if (program == rpc->program) break;
286  }
287  return rpc;
288 }
289 
290 static int validate_packet(const uint8_t *data, uint16_t size, int dir,
291  tAppIdData *flowp, SFSnortPacket *pkt, ServiceRPCData *rd,
292  const char * *pname, uint32_t *program)
293 {
294  const ServiceRPCCall *call;
295  const ServiceRPCReply *reply;
296  const ServiceRPC *rpc;
297  const ServiceRPCPortmap *pm;
298  const ServiceRPCAuth *a;
299  const ServiceRPCPortmapReply *pmr;
300  uint32_t tmp;
301  uint32_t val;
302  const uint8_t *end;
303  tAppIdData *pf;
304  const RPCProgram *rprog;
305 
306  if (!size) return SERVICE_INPROCESS;
307 
308  end = data + size;
309 
310  if (flowp->proto == IPPROTO_UDP)
311  {
312  if (!rd->once)
313  {
314  rd->once = 1;
315  if (size < sizeof(ServiceRPC)) return SERVICE_NOMATCH;
316  rpc = (ServiceRPC *)data;
317  if (ntohl(rpc->type) == RPC_TYPE_REPLY)
318  {
320  rd->state = RPC_STATE_REPLY;
321  dir = APP_ID_FROM_RESPONDER;
322  }
323  }
324  else if (getAppIdFlag(flowp, APPID_SESSION_UDP_REVERSED))
325  {
327  }
328  }
329 
330  switch (rd->state)
331  {
332  case RPC_STATE_CALL:
333  if (dir != APP_ID_FROM_INITIATOR) return SERVICE_INPROCESS;
334  rd->state = RPC_STATE_DONE;
335  if (size < sizeof(ServiceRPCCall)) return SERVICE_NOT_COMPATIBLE;
336  call = (ServiceRPCCall *)data;
337  if (ntohl(call->header.type) != RPC_TYPE_CALL) return SERVICE_NOT_COMPATIBLE;
338  if (ntohl(call->version) != 2) return SERVICE_NOT_COMPATIBLE;
339  rd->program = ntohl(call->program);
340  rd->procedure = ntohl(call->procedure);
341  tmp = ntohl(call->cred.length);
342  if (sizeof(ServiceRPCCall)+tmp > size) return SERVICE_NOT_COMPATIBLE;
343  data += (sizeof(ServiceRPCCall) - sizeof(ServiceRPCAuth)) + tmp;
344  a = (ServiceRPCAuth *)data;
345  tmp = ntohl(a->length);
346  if (tmp+sizeof(ServiceRPCAuth) > (unsigned)(end-data)) return SERVICE_NOT_COMPATIBLE;
347  data += sizeof(ServiceRPCAuth) + tmp;
348  if (rd->program >= 0x60000000) return SERVICE_NOT_COMPATIBLE;
349  switch (rd->program)
350  {
351  case RPC_PROGRAM_PORTMAP:
352  switch (rd->procedure)
353  {
354  case RPC_PORTMAP_GETPORT:
355  if (end-data < (int)sizeof(ServiceRPCPortmap)) return SERVICE_NOT_COMPATIBLE;
356  pm = (ServiceRPCPortmap *)data;
357  rd->proto = pm->proto;
358  break;
359  default:
360  break;
361  }
362  break;
363  default:
364  break;
365  }
366  rd->xid = call->header.xid;
367  rd->state = RPC_STATE_REPLY;
368  break;
369  case RPC_STATE_REPLY:
370  if (dir != APP_ID_FROM_RESPONDER) return SERVICE_INPROCESS;
371  rd->state = RPC_STATE_DONE;
372  if (size < sizeof(ServiceRPCReply)) return SERVICE_NOMATCH;
373  reply = (ServiceRPCReply *)data;
374  if (ntohl(reply->header.type) != RPC_TYPE_REPLY) return SERVICE_NOMATCH;
375  if (rd->xid != reply->header.xid && rd->xid != 0xFFFFFFFF) return SERVICE_NOMATCH;
376  tmp = ntohl(reply->verify.length);
377  if (sizeof(ServiceRPCReply)+tmp > size)
378  return SERVICE_NOMATCH;
379  data += sizeof(ServiceRPCReply) + tmp;
380  tmp = ntohl(reply->reply_state);
381  val = ntohl(reply->state);
382  if (tmp == RPC_REPLY_ACCEPTED)
383  {
384  if (val > RPC_MAX_ACCEPTED) return SERVICE_NOMATCH;
385  if (rd->xid == 0xFFFFFFFF && reply->header.xid != 0xFFFFFFFF)
386  {
387  rd->state = RPC_STATE_CALL;
388  return SERVICE_INPROCESS;
389  }
390  *program = rd->program;
391  switch (rd->program)
392  {
393  case RPC_PROGRAM_PORTMAP:
394  switch (rd->procedure)
395  {
396  case RPC_PORTMAP_GETPORT:
397  if (end-data < (int)sizeof(ServiceRPCPortmapReply))
398  return SERVICE_NOMATCH;
399  pmr = (ServiceRPCPortmapReply *)data;
400  if (pmr->port)
401  {
402  sfaddr_t *sip;
403  sfaddr_t *dip;
404 
405  dip = GET_DST_IP(pkt);
406  sip = GET_SRC_IP(pkt);
407  tmp = ntohl(pmr->port);
408 #ifdef TARGET_BASED
409  pf = rpc_service_mod.api->flow_new(flowp, pkt, dip, 0, sip, (uint16_t)tmp, (uint8_t)ntohl(rd->proto), app_id, 0);
410  if (pf)
411  {
413  flowp->proto==IPPROTO_TCP ? &tcp_svc_element:&svc_element);
415  setAppIdFlag(pf,
416  getAppIdFlag(flowp,
424  }
425 #endif
426  }
427  break;
428  default:
429  break;
430  }
431  *pname = "portmap";
432  break;
433  default:
434  rprog = FindRPCProgram(rd->program);
435  if (rprog && rprog->name) *pname = rprog->name;
436  break;
437  }
438  }
439  else if (tmp == RPC_REPLY_DENIED)
440  {
441  if (val > RPC_MAX_DENIED) return SERVICE_NOMATCH;
442  }
443  else return SERVICE_NOMATCH;
444  rd->state = RPC_STATE_CALL;
445  return SERVICE_SUCCESS;
446  default:
447  return SERVICE_NOMATCH;
448  }
449  return SERVICE_INPROCESS;
450 }
451 
453 {
454  static char subname[64];
455  ServiceRPCData *rd;
456  RNAServiceSubtype sub;
457  RNAServiceSubtype *subtype;
458  uint32_t program = 0;
459  const char *pname = NULL;
460  int rval;
461  tAppIdData *flowp = args->flowp;
462  const uint8_t *data = args->data;
463  SFSnortPacket *pkt = args->pkt;
464  const int dir = args->dir;
465  uint16_t size = args->size;
466 
467  if (!size)
468  {
469  rval = SERVICE_INPROCESS;
470  goto done;
471  }
472 
474  if (!rd)
475  {
476  rd = calloc(1, sizeof(*rd));
477  if (!rd)
478  return SERVICE_ENOMEM;
480  {
481  free(rd);
482  return SERVICE_ENOMEM;
483  }
485  rd->xid = 0xFFFFFFFF;
486  }
487 
488 #ifdef RNA_DEBUG_RPC
489  fprintf(SF_DEBUG_FILE, "Begin %u -> %u %u %d state %d\n", pkt->src_port, pkt->dst_port, flowp->proto, dir, rd->state);
490 #endif
491 
492  rval = validate_packet(data, size, dir, flowp, pkt, rd, &pname, &program);
493 
494 #ifdef RNA_DEBUG_RPC
495  fprintf(SF_DEBUG_FILE, "End %u -> %u %u %d state %d rval %d\n", pkt->src_port, pkt->dst_port, flowp->proto, dir, rd->state, rval);
496 #endif
497 
498 done:
499  switch (rval)
500  {
501  case SERVICE_INPROCESS:
503  {
505  }
506  return SERVICE_INPROCESS;
507 
508  case SERVICE_SUCCESS:
510  {
511  if (pname && *pname)
512  {
513  memset(&sub, 0, sizeof(sub));
514  sub.service = pname;
515  subtype = &sub;
516  }
517  else if (program)
518  {
519  snprintf(subname, sizeof(subname), "(%u)", program);
520  memset(&sub, 0, sizeof(sub));
521  sub.service = subname;
522  subtype = &sub;
523  }
524  else subtype = NULL;
525  rpc_service_mod.api->add_service(flowp, pkt, dir, &svc_element,
526  APP_ID_SUN_RPC, NULL, NULL, subtype, NULL);
527  }
529  return SERVICE_SUCCESS;
530 
533  {
536  args->pConfig, NULL);
537  }
539  return SERVICE_NOT_COMPATIBLE;
540 
541  case SERVICE_NOMATCH:
543  {
544  rpc_service_mod.api->fail_service(flowp, pkt, dir, &svc_element,
546  args->pConfig, NULL);
547  }
549  return SERVICE_NOMATCH;
550  default:
551  return rval;
552  }
553 }
554 
556 {
557  ServiceRPCData *rd;
558  const ServiceRPCFragment *frag;
560  uint32_t fragsize;
561  int ret;
562  int retval = -1;
563  ServiceRPCCall *call;
564  ServiceRPCReply *reply;
565 
566  static char subname[64];
567  RNAServiceSubtype sub;
568  RNAServiceSubtype *subtype;
569  uint32_t program = 0;
570  const char *pname = NULL;
571 
572  tAppIdData *flowp = args->flowp;
573  const uint8_t *data = args->data;
574  SFSnortPacket *pkt = args->pkt;
575  const int dir = args->dir;
576  uint16_t size = args->size;
577 
578  if (!size)
579  goto inprocess;
580 
582  if (!rd)
583  {
584  rd = calloc(1, sizeof(*rd));
585  if (!rd)
586  return SERVICE_ENOMEM;
588  {
589  free(rd);
590  return SERVICE_ENOMEM;
591  }
592  rd->state = RPC_STATE_CALL;
593  for (ret=0; ret<APP_ID_APPID_SESSION_DIRECTION_MAX; ret++)
594  {
595  rd->tcpstate[ret] = RPC_TCP_STATE_FRAG;
597  }
598  }
599 
600  while (size)
601  {
602  fragsize = min(size, (rd->tcpsize[dir] & ~RPC_TCP_FRAG_MASK) -
603  rd->tcpfragpos[dir]);
604 
605  switch (rd->tcpstate[dir])
606  {
607  case RPC_TCP_STATE_FRAG:
608  if (size < sizeof(ServiceRPCFragment)) goto bail;
609  frag = (ServiceRPCFragment *)data;
610  data += sizeof(ServiceRPCFragment);
611  size -= sizeof(ServiceRPCFragment);
612 
613  rd->tcpsize[dir] = ntohl(frag->length);
614  rd->tcpfragpos[dir] = 0;
615  rd->tcpstate[dir] = rd->tcpfragstate[dir];
616  break;
618  if (dir == APP_ID_FROM_INITIATOR)
619  {
620  length = min(fragsize, offsetof(ServiceRPCCall, cred) -
621  rd->tcppos[dir]);
622  memcpy(&rd->tcpdata[dir][rd->tcppos[dir]], data, length);
623  rd->tcppos[dir] += length;
624  rd->tcpfragpos[dir] += length;
625  data += length;
626  size -= length;
627  if (rd->tcppos[dir] >= offsetof(ServiceRPCCall, cred))
628  {
629  call = (ServiceRPCCall *)rd->tcpdata[dir];
630  if (ntohl(call->header.type) != RPC_TYPE_CALL) goto bail;
631  if (ntohl(call->version) != 2) goto bail;
632  rd->tcpstate[dir] = RPC_TCP_STATE_CRED;
633  rd->tcppos[dir] = 0;
634  }
635  }
636  else
637  {
638  length = min(fragsize, offsetof(ServiceRPCReply, verify) -
639  rd->tcppos[dir]);
640  memcpy(&rd->tcpdata[dir][rd->tcppos[dir]], data, length);
641  rd->tcppos[dir] += length;
642  rd->tcpfragpos[dir] += length;
643  data += length;
644  size -= length;
645  if (rd->tcppos[dir] >= offsetof(ServiceRPCReply, verify))
646  {
647  reply = (ServiceRPCReply *)rd->tcpdata[dir];
648  if (ntohl(reply->header.type) != RPC_TYPE_REPLY) goto fail;
649  rd->tcpstate[dir] = RPC_TCP_STATE_VERIFY;
650  rd->tcppos[dir] = 0;
651  }
652  }
653  break;
654  case RPC_TCP_STATE_CRED:
655  if (dir != APP_ID_FROM_INITIATOR)
656  goto bail;
657  length = min(fragsize, sizeof(ServiceRPCAuth) - rd->tcppos[dir]);
658  memcpy(&rd->tcpdata[dir][offsetof(ServiceRPCCall, cred)+rd->tcppos[dir]],
659  data, length);
660  rd->tcppos[dir] += length;
661  rd->tcpfragpos[dir] += length;
662  data += length;
663  size -= length;
664  if (rd->tcppos[dir] >= sizeof(ServiceRPCAuth))
665  {
666  call = (ServiceRPCCall *)rd->tcpdata[dir];
667  length = ntohl(call->cred.length);
668  if (length > (rd->tcpsize[dir] & ~RPC_TCP_FRAG_MASK) ||
669  rd->tcpfragpos[dir]+length > (rd->tcpsize[dir] & ~RPC_TCP_FRAG_MASK))
670  goto bail;
671  rd->tcpauthsize[dir] = length;
673  rd->tcppos[dir] = 0;
674  }
675  break;
677  if (dir != APP_ID_FROM_INITIATOR)
678  goto bail;
679  length = min(fragsize, rd->tcpauthsize[dir] - rd->tcppos[dir]);
680  rd->tcppos[dir] += length;
681  rd->tcpfragpos[dir] += length;
682  data += length;
683  size -= length;
684  if (rd->tcppos[dir] >= rd->tcpauthsize[dir])
685  {
686  call = (ServiceRPCCall *)rd->tcpdata[dir];
687  call->cred.flavor = 0;
688  call->cred.length = 0;
689  rd->tcpstate[dir] = RPC_TCP_STATE_VERIFY;
690  rd->tcppos[dir] = 0;
691  }
692  break;
694  length = min(fragsize, sizeof(ServiceRPCAuth) - rd->tcppos[dir]);
695  if (dir == APP_ID_FROM_INITIATOR)
696  memcpy(&rd->tcpdata[dir][offsetof(ServiceRPCCall, verify)+rd->tcppos[dir]],
697  data, length);
698  else
699  memcpy(&rd->tcpdata[dir][offsetof(ServiceRPCReply, verify)+rd->tcppos[dir]],
700  data, length);
701  rd->tcppos[dir] += length;
702  rd->tcpfragpos[dir] += length;
703  data += length;
704  size -= length;
705  fragsize -= length;
706  if (rd->tcppos[dir] >= sizeof(ServiceRPCAuth))
707  {
708  if (dir == APP_ID_FROM_INITIATOR)
709  {
710  call = (ServiceRPCCall *)rd->tcpdata[dir];
711  length = ntohl(call->verify.length);
712  }
713  else
714  {
715  reply = (ServiceRPCReply *)rd->tcpdata[dir];
716  length = ntohl(reply->verify.length);
717  }
718  if (length > (rd->tcpsize[dir] & ~RPC_TCP_FRAG_MASK) ||
719  rd->tcpfragpos[dir]+length > (rd->tcpsize[dir] & ~RPC_TCP_FRAG_MASK))
720  goto bail;
721  rd->tcpauthsize[dir] = length;
723  rd->tcppos[dir] = 0;
724  }
725  else
726  {
727  break;
728  }
730  length = min(fragsize, rd->tcpauthsize[dir] - rd->tcppos[dir]);
731  rd->tcppos[dir] += length;
732  rd->tcpfragpos[dir] += length;
733  data += length;
734  size -= length;
735  if (rd->tcppos[dir] >= rd->tcpauthsize[dir])
736  {
737  if (dir == APP_ID_FROM_INITIATOR)
738  {
739  call = (ServiceRPCCall *)rd->tcpdata[dir];
740  call->verify.flavor = 0;
741  call->verify.length = 0;
742  rd->tcpstate[dir] = RPC_TCP_STATE_PARTIAL;
743  rd->tcppos[dir] = sizeof(ServiceRPCCall);
744  if (rd->tcpfragpos[dir] >= (rd->tcpsize[dir] & ~RPC_TCP_FRAG_MASK))
745  {
746  if (rd->tcpsize[dir] & RPC_TCP_FRAG_MASK)
747  {
748 
749 #ifdef RNA_DEBUG_RPC
750  fprintf(SF_DEBUG_FILE, "V Begin %u -> %u %u %d state %d\n", pkt->src_port, pkt->dst_port, flowp->proto, dir, rd->state);
751 #endif
752 
753  ret = validate_packet(rd->tcpdata[dir], rd->tcppos[dir], dir, flowp, pkt,
754  rd, &pname, &program);
755 
756 #ifdef RNA_DEBUG_RPC
757  fprintf(SF_DEBUG_FILE, "V End %u -> %u %u %d state %d rval %d\n", pkt->src_port, pkt->dst_port, flowp->proto, dir, rd->state, ret);
758 #endif
759 
760  if (retval == -1) retval = ret;
762  rd->tcppos[dir] = 0;
763  }
764  else rd->tcpfragstate[dir] = rd->tcpstate[dir];
765  rd->tcpstate[dir] = RPC_TCP_STATE_FRAG;
766  }
767  }
768  else
769  {
770  reply = (ServiceRPCReply *)rd->tcpdata[dir];
771  reply->verify.flavor = 0;
772  reply->verify.length = 0;
774  if (rd->tcpfragpos[dir]+sizeof(uint32_t) > (rd->tcpsize[dir] & ~RPC_TCP_FRAG_MASK))
775  goto bail;
776  rd->tcppos[dir] = 0;
777  }
778  }
779  break;
781  if (dir != APP_ID_FROM_RESPONDER) goto bail;
782  length = min(fragsize, sizeof(uint32_t) - rd->tcppos[dir]);
783  memcpy(&rd->tcpdata[dir][offsetof(ServiceRPCReply, state)+rd->tcppos[dir]],
784  data, length);
785  rd->tcppos[dir] += length;
786  rd->tcpfragpos[dir] += length;
787  data += length;
788  size -= length;
789 
790  if (rd->tcppos[dir] >= sizeof(uint32_t))
791  {
792  rd->tcpstate[dir] = RPC_TCP_STATE_PARTIAL;
793  rd->tcppos[dir] = sizeof(ServiceRPCReply);
794  }
795  if (rd->tcpfragpos[dir] >= (rd->tcpsize[dir] & ~RPC_TCP_FRAG_MASK))
796  {
797  fragsize = 0;
798  }
799  else
800  {
801  break;
802  }
804  if (rd->tcppos[dir] < RPC_MAX_TCP_PACKET_SIZE && fragsize)
805  {
806  length = min(fragsize, RPC_MAX_TCP_PACKET_SIZE - rd->tcppos[dir]);
807  memcpy(&rd->tcpdata[dir][rd->tcppos[dir]], data, length);
808  rd->tcppos[dir] += length;
809  }
810  else
811  {
812  length = fragsize;
813  }
814  rd->tcpfragpos[dir] += length;
815  data += length;
816  size -= length;
817  if (rd->tcpfragpos[dir] >= (rd->tcpsize[dir] & ~RPC_TCP_FRAG_MASK))
818  {
819  if (rd->tcpsize[dir] & RPC_TCP_FRAG_MASK)
820  {
821 
822 #ifdef RNA_DEBUG_RPC
823  fprintf(SF_DEBUG_FILE, "P Begin %u -> %u %u %d state %d\n", pkt->src_port, pkt->dst_port, flowp->proto, dir, rd->state);
824 #endif
825 
826  ret = validate_packet(rd->tcpdata[dir], rd->tcppos[dir], dir, flowp, pkt,
827  rd, &pname, &program);
828 
829 #ifdef RNA_DEBUG_RPC
830  fprintf(SF_DEBUG_FILE, "P End %u -> %u %u %d state %d rval %d\n", pkt->src_port, pkt->dst_port, flowp->proto, dir, rd->state, ret);
831 #endif
832 
833  if (retval == -1) retval = ret;
835  rd->tcppos[dir] = 0;
836  }
837  else rd->tcpfragstate[dir] = rd->tcpstate[dir];
838  rd->tcpstate[dir] = RPC_TCP_STATE_FRAG;
839  }
840  break;
841  default:
842  if (retval == -1) goto fail;
843  else
844  {
846  goto done;
847  }
848  }
849  if (rd->tcpstate[dir] != RPC_TCP_STATE_FRAG &&
850  rd->tcpstate[dir] != RPC_TCP_STATE_PARTIAL &&
851  rd->tcpfragpos[dir] >= (rd->tcpsize[dir] & ~RPC_TCP_FRAG_MASK))
852  {
853  if (rd->tcpsize[dir] & RPC_TCP_FRAG_MASK) goto bail;
854  rd->tcpfragstate[dir] = rd->tcpstate[dir];
855  rd->tcpstate[dir] = RPC_TCP_STATE_FRAG;
856  }
857  }
858  if (retval == -1) retval = SERVICE_INPROCESS;
859 
860 done:
861  switch (retval)
862  {
863  case SERVICE_INPROCESS:
864 inprocess:
866  {
868  }
869  return SERVICE_INPROCESS;
870 
871  case SERVICE_SUCCESS:
873  {
874  if (pname && *pname)
875  {
876  memset(&sub, 0, sizeof(sub));
877  sub.service = pname;
878  subtype = &sub;
879  }
880  else if (program)
881  {
882  sprintf(subname, "(%u)", program);
883  memset(&sub, 0, sizeof(sub));
884  sub.service = subname;
885  subtype = &sub;
886  }
887  else subtype = NULL;
888  rpc_service_mod.api->add_service(flowp, pkt, dir, &tcp_svc_element,
889  APP_ID_SUN_RPC, NULL, NULL, subtype, NULL);
890  }
892  return SERVICE_SUCCESS;
893 
896  {
899  args->pConfig, NULL);
900  }
902  return SERVICE_NOT_COMPATIBLE;
903 
904  case SERVICE_NOMATCH:
905 fail:
907  {
908  rpc_service_mod.api->fail_service(flowp, pkt, dir, &tcp_svc_element,
910  args->pConfig, NULL);
911  }
913  return SERVICE_NOMATCH;
914  default:
915  return retval;
916  }
917 
918 bail:
922  if (dir == APP_ID_FROM_INITIATOR)
923  {
924  if (retval == -1) retval = SERVICE_NOT_COMPATIBLE;
925  }
926  else
927  {
928  if (retval == -1) retval = SERVICE_NOMATCH;
929  }
930  goto done;
931 }
932 
933 static void rpc_clean(const CleanServiceAPI * const clean_api)
934 {
935  RPCProgram *prog = NULL;
936 
937  while(rpc_programs)
938  {
939  prog = rpc_programs;
940 
942 
943  if(prog->name)
944  free(prog->name);
945 
946  free(prog);
947  }
948 }
#define APPID_SESSION_DISCOVER_USER
Definition: appIdApi.h:39
#define APPID_SESSION_RESPONDER_CHECKED
Definition: appIdApi.h:78
#define APPID_SESSION_DISCOVER_APP
Definition: appIdApi.h:74
#define APPID_SESSION_INITIATOR_MONITORED
Definition: appIdApi.h:35
#define APPID_SESSION_INITIATOR_CHECKED
Definition: appIdApi.h:79
#define APPID_SESSION_SPECIAL_MONITORED
Definition: appIdApi.h:36
#define APPID_SESSION_RESPONDER_MONITORED
Definition: appIdApi.h:34
#define APPID_SESSION_CONTINUE
Definition: appIdApi.h:66
#define APPID_SESSION_UDP_REVERSED
Definition: appIdApi.h:50
#define APPID_SESSION_SERVICE_DETECTED
Definition: appIdApi.h:54
@ APP_ID_FROM_INITIATOR
Definition: appId.h:1036
@ APP_ID_APPID_SESSION_DIRECTION_MAX
Definition: appId.h:1038
@ APP_ID_FROM_RESPONDER
Definition: appId.h:1037
@ APP_ID_SUN_RPC
Definition: appId.h:479
@ APPINFO_FLAG_SERVICE_UDP_REVERSED
Definition: appInfoTable.h:37
@ APPINFO_FLAG_SERVICE_ADDITIONAL
Definition: appInfoTable.h:36
static CleanClientAppAPI clean_api
#define strdup
Definition: config.h:212
#define snprintf
Definition: config.h:206
#define SF_DEBUG_FILE
Definition: flow.h:38
@ RNA_STATE_STATEFUL
Definition: flow.h:59
static uint64_t getAppIdFlag(tAppIdData *flow, uint64_t flags)
Definition: flow.h:387
static void setAppIdFlag(tAppIdData *flow, uint64_t flags)
Definition: flow.h:365
static void clearAppIdFlag(tAppIdData *flow, uint64_t flags)
Definition: flow.h:376
#define GET_SRC_IP(p)
Definition: ipv6_port.h:41
#define GET_DST_IP(p)
Definition: ipv6_port.h:42
@ SERVICE_ENOMEM
Definition: service_api.h:51
@ SERVICE_NOT_COMPATIBLE
Definition: service_api.h:45
@ SERVICE_SUCCESS
Definition: service_api.h:42
@ SERVICE_NOMATCH
Definition: service_api.h:48
@ SERVICE_INPROCESS
Definition: service_api.h:43
static tAppRegistryEntry appIdRegistry[]
Definition: service_rpc.c:223
static void rpc_clean(const CleanServiceAPI *const clean_api)
Definition: service_rpc.c:933
#define RPC_PORT_NLOCKMGR
Definition: service_rpc.c:184
static int rpc_tcp_validate(ServiceValidationArgs *args)
Definition: service_rpc.c:555
struct _SERVICE_RPC_PORTMAP_REPLY ServiceRPCPortmapReply
static RPCProgram * rpc_programs
Definition: service_rpc.c:218
RPCReplyState
Definition: service_rpc.c:62
@ RPC_REPLY_MID
Definition: service_rpc.c:65
@ RPC_REPLY_MULTI
Definition: service_rpc.c:64
@ RPC_REPLY_BEGIN
Definition: service_rpc.c:63
struct _SERVICE_RPC_DATA ServiceRPCData
#define RPC_MAX_TCP_PACKET_SIZE
Definition: service_rpc.c:85
struct _SERVICE_RPC_CALL_HEADER ServiceRPCCall
#define RPC_PORT_NFS
Definition: service_rpc.c:182
static uint8_t rpc_reply_denied_pattern[8]
Definition: service_rpc.c:221
struct _SERVICE_RPC_REPLY_HEADER ServiceRPCReply
RPCTCPState
Definition: service_rpc.c:49
@ RPC_TCP_STATE_VERIFY_DATA
Definition: service_rpc.c:55
@ RPC_TCP_STATE_CRED
Definition: service_rpc.c:52
@ RPC_TCP_STATE_VERIFY
Definition: service_rpc.c:54
@ RPC_TCP_STATE_FRAG
Definition: service_rpc.c:50
@ RPC_TCP_STATE_REPLY_HEADER
Definition: service_rpc.c:56
@ RPC_TCP_STATE_HEADER
Definition: service_rpc.c:51
@ RPC_TCP_STATE_DONE
Definition: service_rpc.c:58
@ RPC_TCP_STATE_PARTIAL
Definition: service_rpc.c:57
@ RPC_TCP_STATE_CRED_DATA
Definition: service_rpc.c:53
static int rpc_validate(ServiceValidationArgs *args)
Definition: service_rpc.c:452
static RNAServiceValidationPort pp[]
Definition: service_rpc.c:186
#define RPC_REPLY_DENIED
Definition: service_rpc.c:77
struct _SERVICE_RPC_AUTH ServiceRPCAuth
#define RPC_TYPE_CALL
Definition: service_rpc.c:70
tRNAServiceValidationModule rpc_service_mod
Definition: service_rpc.c:203
#define RPC_TYPE_REPLY
Definition: service_rpc.c:71
#define RPC_TCP_FRAG_MASK
Definition: service_rpc.c:82
#define RPC_PORT_PORTMAPPER
Definition: service_rpc.c:181
static uint8_t rpc_reply_accepted_pattern[8]
Definition: service_rpc.c:220
struct _SERVICE_RPC_PORTMAP ServiceRPCPortmap
#define RPC_MAX_DENIED
Definition: service_rpc.c:80
static int rpc_init(const InitServiceAPI *const init_api)
Definition: service_rpc.c:230
RPCState
Definition: service_rpc.c:42
@ RPC_STATE_REPLY
Definition: service_rpc.c:44
@ RPC_STATE_CALL
Definition: service_rpc.c:43
@ RPC_STATE_DONE
Definition: service_rpc.c:45
#define RPC_PROGRAM_PORTMAP
Definition: service_rpc.c:73
#define RPC_PORTMAP_GETPORT
Definition: service_rpc.c:74
struct _SERVICE_RPC_HEADER ServiceRPC
#define min(x, y)
Definition: service_rpc.c:68
struct _RPC_PROGRAM RPCProgram
static int validate_packet(const uint8_t *data, uint16_t size, int dir, tAppIdData *flowp, SFSnortPacket *pkt, ServiceRPCData *rd, const char **pname, uint32_t *program)
Definition: service_rpc.c:290
#define RPC_REPLY_ACCEPTED
Definition: service_rpc.c:76
#define RPC_PORT_MOUNTD
Definition: service_rpc.c:183
static tRNAServiceElement tcp_svc_element
Definition: service_rpc.c:171
static int16_t app_id
Definition: service_rpc.c:228
static tRNAServiceElement svc_element
Definition: service_rpc.c:162
#define RPC_MAX_ACCEPTED
Definition: service_rpc.c:79
struct _SERVICE_RPC_FRAG ServiceRPCFragment
static const RPCProgram * FindRPCProgram(uint32_t program)
Definition: service_rpc.c:279
#define DETECTOR_TYPE_DECODER
Definition: service_state.h:78
DynamicPreprocessorData _dpd
unsigned int length
Definition: sf_sechash.c:55
#define DEBUG_LOG
Definition: snort_debug.h:53
__int16 int16_t
Definition: stdint.h:27
uint8_t proto
Definition: flow.h:248
RNA_INSPECTION_STATE rnaServiceState
Definition: flow.h:260
struct RNAServiceElement * next
Definition: service_api.h:112
const ServiceApi * api
Definition: service_api.h:217
DynamicPreprocessorData * dpd
Definition: service_api.h:99
void(* RegisterAppId)(RNAServiceValidationFCN fcn, tAppId appId, uint32_t additionalInfo, struct appIdConfig_ *pConfig)
Definition: service_api.h:95
void(* RegisterPattern)(RNAServiceValidationFCN fcn, uint8_t proto, const uint8_t *pattern, unsigned size, int position, const char *name, struct appIdConfig_ *pConfig)
Definition: service_api.h:87
struct appIdConfig_ * pAppidConfig
AppId context for which this API should be used.
Definition: service_api.h:100
const char * service
Definition: appIdApi.h:120
struct _RPC_PROGRAM * next
Definition: service_rpc.c:213
uint32_t program
Definition: service_rpc.c:214
ServiceInProcess service_inprocess
Definition: service_api.h:184
IncompatibleData incompatible_data
Definition: service_api.h:185
ServiceFlowdataAddId data_add_id
Definition: service_api.h:178
ServiceFlowdataGet data_get
Definition: service_api.h:175
AddService add_service
Definition: service_api.h:182
ServiceCreateNewFlow flow_new
Definition: service_api.h:177
ServiceFlowdataAdd data_add
Definition: service_api.h:176
FailService fail_service
Definition: service_api.h:183
ServiceRPCAuth verify
Definition: service_rpc.c:127
RPCTCPState tcpfragstate[APP_ID_APPID_SESSION_DIRECTION_MAX]
Definition: service_rpc.c:144
uint8_t tcpdata[APP_ID_APPID_SESSION_DIRECTION_MAX][56]
Definition: service_rpc.c:153
RPCTCPState tcpstate[APP_ID_APPID_SESSION_DIRECTION_MAX]
Definition: service_rpc.c:143
uint32_t tcpsize[APP_ID_APPID_SESSION_DIRECTION_MAX]
Definition: service_rpc.c:149
uint32_t tcppos[APP_ID_APPID_SESSION_DIRECTION_MAX]
Definition: service_rpc.c:152
uint32_t tcpfragpos[APP_ID_APPID_SESSION_DIRECTION_MAX]
Definition: service_rpc.c:150
uint32_t procedure
Definition: service_rpc.c:146
uint32_t tcpauthsize[APP_ID_APPID_SESSION_DIRECTION_MAX]
Definition: service_rpc.c:151
SFSnortPacket * pkt
Definition: service_api.h:60
const uint8_t * data
Definition: service_api.h:56
tAppIdData * flowp
Definition: service_api.h:59
const struct appIdConfig_ * pConfig
Definition: service_api.h:62
Definition: sf_ip.h:91
Definition: rpc.h:83
char * r_name
Definition: rpc.h:84
int r_number
Definition: rpc.h:86
#define NULL
Definition: types.h:63
unsigned short uint16_t
Definition: u2openappid.c:53
unsigned int uint32_t
Definition: u2openappid.c:52
unsigned char uint8_t
Definition: u2openappid.c:54