Ejemplo n.º 1
0
/* find_http_req DATA LEN FOUND FOUNDLEN
 * Look for an HTTP request and response in buffer DATA of length LEN. The
 * return value is a pointer into DATA suitable for a subsequent call to this
 * function; *FOUND is either NULL, or a pointer to the start of an HTTP
 * request; in the latter case, *FOUNDLEN is the length of the match
 * containing enough information to obtain the URL. */
unsigned char *find_http_req(const unsigned char *data, const size_t len, unsigned char **http, size_t *httplen) {
    unsigned char *req, *le, *blankline, *hosthdr;
    
#define remaining(x)    (len - (data - (x)))
#define MAX_REQ         16384
    
    /* HTTP requests look like:
     *
     *      GET {path} HTTP/1.(0|1)\r\n
     *      header: value\r\n
     *          ...
     *      \r\n
     *
     * We may care about the Host: header in the request. */
    if (len < 40)
        return (unsigned char*)data;
    
    if (!(req = memstr(data, len, (unsigned char*) "GET ", 4)))
        return (unsigned char*)(data + len - 4);

    /* Find the end of the request line. */
    if (!(le = memstr(req + 4, remaining(req + 4), (unsigned char*) "\r\n", 2))) {
        if (remaining(req + 4) > MAX_REQ)
            return (unsigned char*)(req + 4);
        else
            return (unsigned char*)req;
    }

    /* Not enough space for a path. */
    if (le < req + 5)
        return le + 2;

    /* Not an HTTP request, just a line starting GET.... */
    if (memcmp(le - 9, " HTTP/1.", 8) || !strchr("01", (int)*(le - 1)))
        return le + 2;

    /* Find the end of the request headers. */
    if (!(blankline = memstr(le + 2, remaining(le + 2), (unsigned char*) "\r\n\r\n", 4))) {
        if (remaining(le + 2) > MAX_REQ)
            return (unsigned char*)(data + len - 4);
        else
            return req;
    }

    if (memcmp(req + 4, "http://", 7) == 0)
        /* Probably a cache request; in any case, don't need to look for a Host:. */
        goto found;

    /* Is there a Host: header? */
    if (!(hosthdr = memstr(le, blankline - le + 2, (unsigned char*) "\r\nHost: ", 8))) {
        return blankline + 4;
    }

found:
    
    *http = req;
    *httplen = blankline - req;

    return blankline + 4;
}
Ejemplo n.º 2
0
TEST(MiscTests, MemStr) {
    const char text[] = "zaqwsxcderfv543\xa6\00bnmjhgfrtcsKOTEKequdo825dgqjx92jdDCSIvfds9*%c3@^((b%^((*gswtysirkkwpfceoioGt7j";
    const char pat1[] = "KOTEK";
    const char pat2[] = "KO£EK";

    EXPECT_NE(memstr(text, pat1, sizeof(pat1) - 1), nullptr);
    EXPECT_EQ(memstr(text, pat2, sizeof(pat2) - 1), nullptr);
}
Ejemplo n.º 3
0
unsigned char *find_jpeg_image(const unsigned char *data, const size_t len, unsigned char **jpegdata, size_t *jpeglen)
{
    unsigned char *jpeghdr;

    *jpegdata = NULL;
    *jpeglen = 0;

    if (data == NULL) {
        return NULL;
    }

    /* find SOI marker */
    jpeghdr = memstr(data, len, (unsigned char*)"\xff\xd8", 2);
    if (!jpeghdr) return (unsigned char*)(data + len - 1);

    jpg_segment_t* segment;
    unsigned int segment_lenght = 2;
    unsigned char *block = jpeghdr;

    do {
        /* more data to advance ? */
        if (data + len < block + segment_lenght) {
            break;
        }

        /* advance to next block */
        block = block + segment_lenght;
        segment = (jpg_segment_t*) block;
        segment_lenght = is_jpeg_segment(segment);

        /*
         * start of scan
         *
         * XXX: dunno how to parse...
         */
        if (segment->marker_type == SOS) {
            block = memstr(block, len - (block - data), (unsigned char*)"\xff\xd9", 2);

            if (block) {
                *jpegdata = jpeghdr;
                *jpeglen = block + 2 - jpeghdr;
                return block + 2;
            } else break;
        }

    } while (segment_lenght != 0);

    return jpeghdr;
}
Ejemplo n.º 4
0
// 粘贴内存解析战果
BOOL CAirLogEx::PasteMemory(CHAR* lpMemory, DWORD dwsize)
{
	DWORD dwOutsize = 0;
	CHAR* lpfltMemory = this->CharFilter(lpMemory, dwsize, FILTER_CHAR, &dwOutsize);
	BOOL bRet = FALSE;
	if (lpfltMemory)
	{
		CHAR* lpHead = memstr(lpfltMemory, BLOCK_ENDOFGAMESTATS, dwOutsize);
		if (lpHead)
		{
			lpHead += lstrlenA(BLOCK_ENDOFGAMESTATS);
			int nbodySize = dwOutsize - (lpHead - lpfltMemory);
			this->CutAllBlock(lpHead, nbodySize);
			if ( SWF_ERR_INT != this->GetFirstSummBlock(EndofGameStats.teamPlayerParticipantStats/*, lpfltMemory, dwsize*/) )
			{
				int airIdx = this->GetPointsPenaltyBlock(&EndofGameStats.PointsPenalty);
				if (SWF_ERR_INT != airIdx)
				{
					if ( SWF_ERR_INT != this->GetNextSummBlock(EndofGameStats.otherTeamPlayerParticipantStats, airIdx) )
					{
						if ( SWF_ERR_INT != this->GetEndOfGameBlock(&EndofGameStats) )
							bRet = TRUE;
					}
				}
			}
		}
		this->FreeFilterStr(lpfltMemory);
	}
	FreeAirMemory(m_airMemoryArr.begin(), m_airMemoryArr.size());
	return bRet;
}
Ejemplo n.º 5
0

int rtl_mime_get_boundry(char *query_string, int query_string_len)
{
	char *substr_start,*ptr;
	char *substr="----------------------------";
	substr_start=memstr(query_string,substr,query_string_len);
	if(substr_start==NULL)
	{
		printf("can't get boundry string\n");
		return -1;
	}
	int i=0;
	ptr=substr_start;
	while( (ptr[i] !=0x0d || ptr[i+1] !=0x0a) && i<MAX_BOUNDRY_LEN)
	{	
		str_boundry[i]=ptr[i];
		i++;
	}
	if(i>=MAX_BOUNDRY_LEN)
	{
		printf("the string of boundry is too long\n");
		return -1;
	}
	str_boundry[i]=0;
Ejemplo n.º 6
0
int Add_To_Heap(char *s,int fancy)
{
  int old_ofs;
  char *o;

  /* If string is already in table, no need to add! */

  if ((o=memstr(strings,s,offset,strlen(s)+1)) != NULL)
    old_ofs=o-strings;
  else
  {
    strcpy(strings+offset,s);
    old_ofs=offset;
    offset += strlen(s)+1;
#ifndef UNIX
    if (fancy)
      fancy_fn(strings+old_ofs);
#endif      
  }

  if (offset >= HEAP_SIZE)
  {
    printf("\n\aRan out of memory while adding `%s' to .PRM heap.\n",s);
    exit(1);
  }

  return old_ofs;
}
Ejemplo n.º 7
0
// Print a classic memory dump with configurable base and grouping.
void memdump(const char* data, size_t length, u_int8_t base, u_int8_t gsize, u_int8_t gcount)
{
    int group_size = gsize;
    int group_count = gcount;
    
    int line_width = group_size * group_count;
    unsigned int offset = 0;
    while (length > offset) {
        const char* line = &data[offset];
        size_t lineMax = MIN((length - offset), line_width);
        printf("  %p %06u |", &line[0], offset);
        for (int c = 0; c < lineMax; c++) {
            if ( (c % group_size) == 0 ) printf(" ");
            char* str = memstr(&line[c], 1, base);
            printf("%s ", str); FREE_BUFFER(str);
        }
        printf("|");
        for (int c = 0; c < lineMax; c++) {
            if ( (c % group_size) == 0 ) printf(" ");
            char chr = line[c] & 0xFF;
            if (chr < 32) // ASCII unprintable
                chr = '.';
            printf("%c", chr);
        }
        printf(" |\n");
        offset += line_width;
    }
}
Ejemplo n.º 8
0
}
	
char *rtl_mime_get_name(char *query_string,char *param,int query_string_len)
{
	char *ptr=NULL;
	ptr=memstr(query_string,param,query_string_len);
	if(ptr==NULL)
		return NULL;
Ejemplo n.º 9
0
void listenmain(void)
{
	int size, ip_size;
	int stdoutFD = fileno(stdout);
	char packet[IP_MAX_SIZE+linkhdr_size];
	char *p, *ip_packet;
	struct myiphdr ip;
	__u16 id;
	static __u16 exp_id; /* expected id */

	exp_id = 1;

	while(1) {
		size = read_packet(packet, IP_MAX_SIZE+linkhdr_size);
		switch(size) {
		case 0:
			continue;
		case -1:
			exit(1);
		}
	
		/* Skip truncated packets */
		if (size < linkhdr_size+IPHDR_SIZE)
			continue;
		ip_packet = packet + linkhdr_size;

		/* copy the ip header so it will be aligned */
		memcpy(&ip, ip_packet, sizeof(ip));
		id = ntohs(ip.id);
		ip_size = ntohs(ip.tot_len);
		if (size-linkhdr_size > ip_size)
			size = ip_size;
		else
			size -= linkhdr_size;

		if ((p = memstr(ip_packet, sign, size))) {
			if (opt_verbose)
				fprintf(stderr, "packet %d received\n", id);

			if (opt_safe) {
				if (id == exp_id)
					exp_id++;
				else {
					if (opt_verbose)
						fprintf(stderr, "packet not in sequence (id %d) received\n", id);
					send_hcmp(HCMP_RESTART, exp_id);
					if (opt_verbose)
						fprintf(stderr, "HCMP restart from %d sent\n", exp_id);
					continue; /* discard this packet */
				}
			}

			p+=strlen(sign);
			write(stdoutFD, p, size-(p-ip_packet));
		}
	}
}
Ejemplo n.º 10
0
}
	
char *rtl_mime_find_boundry(char *query_string, int query_string_len)
{
	char *substr_start;	
	substr_start=memstr(query_string,str_boundry,query_string_len);
	if(substr_start==NULL)
		return NULL;
	int len=strlen(str_boundry);
	substr_start+=len;	 
Ejemplo n.º 11
0
Archivo: string.c Proyecto: mwanna/v7
static void Str_split(struct v7_c_func_arg *cfa) {
  const struct v7_string *s = &cfa->this_obj->v.str;
  const char *p1, *p2, *e = s->buf + s->len;
  int limit = cfa->num_args == 2 && cfa->args[1]->type == V7_TYPE_NUM ?
  cfa->args[1]->v.num : -1;
  int num_elems = 0;

  v7_set_class(cfa->result, V7_CLASS_ARRAY);
  if (cfa->num_args == 0) {
    v7_append(cfa->v7, cfa->result,
              v7_mkv(cfa->v7, V7_TYPE_STR, s->buf, s->len, 1));
  } else if (cfa->args[0]->type == V7_TYPE_STR) {
    const struct v7_string *sep = &cfa->args[0]->v.str;
    if (sep->len == 0) {
      // Separator is empty. Split string by characters.
      for (p1 = s->buf; p1 < e; p1++) {
        if (limit >= 0 && limit <= num_elems) return;
        v7_append(cfa->v7, cfa->result, v7_mkv(cfa->v7, V7_TYPE_STR, p1, 1, 1));
        num_elems++;
      }
    } else {
      p1 = s->buf;
      while ((p2 = memstr(p1, e - p1, sep->buf, sep->len)) != NULL) {
        if (limit >= 0 && limit <= num_elems) return;
        v7_append(cfa->v7, cfa->result,
                  v7_mkv(cfa->v7, V7_TYPE_STR, p1, p2 - p1, 1));
        p1 = p2 + sep->len;
        num_elems++;
      }
      if (limit < 0 || limit > num_elems) {
        v7_append(cfa->v7, cfa->result,
                  v7_mkv(cfa->v7, V7_TYPE_STR, p1, e - p1, 1));
      }
    }
  } else if (instanceof(cfa->args[0], &s_constructors[V7_CLASS_REGEXP])) {
    char regex[200];
    struct slre_cap caps[20];
    int n = 0;

    snprintf(regex, sizeof(regex), "(%s)", cfa->args[0]->v.regex);
    p1 = s->buf;
    while ((n = slre_match(regex, p1, e - p1, caps, ARRAY_SIZE(caps), 0)) > 0) {
      if (limit >= 0 && limit <= num_elems) return;
      v7_append(cfa->v7, cfa->result,
                v7_mkv(cfa->v7, V7_TYPE_STR, p1, caps[0].ptr - p1, 1));
      p1 += n;
      num_elems++;
    }
    if (limit < 0 || limit > num_elems) {
      v7_append(cfa->v7, cfa->result,
                v7_mkv(cfa->v7, V7_TYPE_STR, p1, e - p1, 1));
    }
  }
}
Ejemplo n.º 12
0
static char
*getLineBreak( SMTPBuffer *sb )
{

   static const char mName[] = "getLineBreak";

   if ( sb->NetworkUsed == 0)
      return NULL;

   return memstr(sb->NetworkBuffer, crlf, sb->NetworkUsed);

} /* END getLineBreak */
Ejemplo n.º 13
0
static int http_parse_mime(uchar *tcp_data, ushort tcp_data_len, uchar nr)
{
	uchar 	*ptr;
	uint	data_len;
	uint	mem_len;

	/* skip boundary="boundary code" */
	if ((ptr = (uchar *)strstr((const char *)tcp_data, 
			boundary_code)) == NULL)
		return 1;
	else 
		ptr = ptr + strlen(boundary_code);

	mem_len = tcp_data_len - (ptr - tcp_data);
	
	/* find the first boundary code */
	if ((ptr = (uchar *)memstr((const char *)ptr, 
			boundary_code, mem_len)) != NULL) {
		/* the first content length */
		post_info.rcv_len = tcp_data_len - (ptr - tcp_data) + 2;
		
		/* move pointer to Content-Disposition */
		ptr = ptr + strlen(boundary_code);

		/* get upload file name */
		ptr = (uchar *)strstr((const char *)ptr, c_fname);
		ptr = (uchar *)strchr((const char *)ptr,'"');
		if (*(ptr+1) == '"') {
			printf("No file to be uploaded !!!\n");
			http_state = HTTP_START;
			http_send_error(nr, 400, "Bad Request",
					 "No upload file name to be slected !");
			return 1;
		} else {
			/* printf("Parsing file name...\n"); */
		}
								
	} else {
		/*printf("Can't find the first boundary code.\n");*/
		return 1;
	}
	
	ptr = (uchar *)strstr((const char *)ptr, c_headerend); /* "\r\n\r\n" */
	ptr = ptr + strlen(c_headerend);	/* upload file start pointer */
	
	data_len = tcp_data_len - (ptr - tcp_data );
	post_info.data_len = data_len;
	memcpy(post_info.buf, ptr, data_len);
	
	return 0;
}
Ejemplo n.º 14
0
void dispatch_http_req(const char *mname, const unsigned char *data, const size_t len) {
    char *url;
    const char *path, *host;
    int pathlen, hostlen;
    const unsigned char *p;

    if (!(p = memstr(data, len, (unsigned char*)"\r\n", 2)))
        return;

    path = (const char*)(data + 4);
    pathlen = (p - 9) - (unsigned char*)path;

    if (memcmp(path, "http://", 7) == 0) {
        url = malloc(pathlen + 1);
        sprintf(url, "%.*s", pathlen, path);
    } else {

        if (!(p = memstr(p, len - (p - data), (unsigned char*)"\r\nHost: ", 8)))
            return;

        host = (const char*)(p + 8);

        if (!(p = memstr(p + 8, len - (p + 8 - data), (unsigned char*)"\r\n", 2)))
            return;

        hostlen = p - (const unsigned char*)host;

        if (hostlen == 0)
            return;

        url = malloc(hostlen + pathlen + 9);
        sprintf(url, "http://%.*s%.*s", hostlen, host, pathlen, path);
    }

    fprintf(stderr, "\n\n  %s\n\n", url);
    free(url);
}
Ejemplo n.º 15
0
int main() {
	setvbuf(stdin,  NULL, _IONBF, 0);
	setvbuf(stdout, NULL, _IONBF, 0);

	alarm(10);
	welcome();

	printf("Show me your shellcode (max = %zi bytes): ", sizeof(shellcode));
	read(0, shellcode, sizeof(shellcode));
	if(memstr(shellcode, "flag", sizeof(shellcode))){
		puts("Oops!");
		exit(0);
	}

	(*(void(*)())shellcode)();

	return 0;
}
Ejemplo n.º 16
0
/* code not used !*/
int buffered_printer(int infd)
{
   int i,k=0,retval;
   char *missatge=0,*myerror="";
   struct sip_msg msg;
   static char mybuffer[1400];
   static int end=0,last=0;

   while((i=read(infd,&mybuffer[last],1400-last))==1400-last){
      if((end=memstr(mybuffer,last+i,"\n\n\n",3))<0){
	 last+=i;
	 return 0;
      }else{
	 end+=3;
	 while(end<1400 && (mybuffer[end]=='\n' || mybuffer[end]=='.' || mybuffer[end]=='\r'))
	    end++;
	 if((missatge=pkg_malloc(end))==0){
	    myerror="Out of memory !!\n";
	    goto error;
	 }
	 memset(missatge,0,end);
	 memcpy(missatge,mybuffer,end);
	 memset(&msg,0,sizeof(struct sip_msg));
	 msg.buf=missatge;
	 msg.len=end;
	 if(!parse_msg(msg.buf,msg.len,&msg))
	    print_msg_info(1,&msg);
	 printf("PARSED:%d,last=%d,end=%d\n",k++,last,end);
	 free_sip_msg(&msg);
	 pkg_free(missatge);
	 memmove(mybuffer,&mybuffer[end],1400-end);
	 last=1400-end;
      }
   }
   retval=0;
   goto exit;
error:
   printf("Error on %s",myerror);
   retval=1;
exit:
   if(missatge)
      pkg_free(missatge);
   return retval;
}
Ejemplo n.º 17
0
BOOL Replace(_Buffer *inb, /*_Buffer *outb, */char *from, int index)
{
	char *a = memstr(inb->m_buf, from, inb->Len());
	if (a)
	{
		_Buffer b1;
		b1.Append(inb->m_buf, a - inb->m_buf);
		char buff[1024];
		sprintf(buff, "<img src=\"%s%d\">", m_Path.Ptr(), index);
//		sprintf(buff, "<img src=\"%s%d\">", m_Path.Ptr(), 999);
		b1.Append(buff);
		b1.Append(a + strlen(from), inb->Len() - (a-inb->m_buf) - strlen(from));
		inb->Clear();
		inb->Append(b1.Ptr(), b1.Len());
		return TRUE;
	}
	
	return FALSE;
}
Ejemplo n.º 18
0
void readmacredboot(char *flash, char *redbootconfig)
{
	int fd, i;
	off_t flashsize;
	void *m, *mac;
	char name[32];

	if ((fd = open(flash, O_RDONLY)) < 0) {
		perror("setmac: failed to open MAC flash");
		return;
	}

	m = malloc(REDBOOTSIZE);
	if (!m) {
		fprintf(stderr, "setmac: malloc failed\n");
		close(fd);
		return;
	}

	flashsize = read(fd, m, REDBOOTSIZE);
	if (flashsize < 0) {
		perror("setmac: failed to read MAC flash");
		close(fd);
		free(m);
		return;
	}

	for (i = 0; (i < numeths); i++) {
		snprintf(name, sizeof(name), redbootconfig, i);
		mac = memstr(m, name, flashsize);
		if (!mac) {
			fprintf(stderr, "setmac: redboot config '%s' not found\n",
					name);
			continue;
		}
		mac += strlen(name)+1;
		memcpy(&mactable[i*6], mac, 6);
	}

	free(m);
	close(fd);
}
Ejemplo n.º 19
0
Archivo: gmcpubar.c Proyecto: vmj/gmbar
static long
parse_cpuinfo(const char* cpuinfo, const unsigned int size)
{
        const char* p = cpuinfo;
        unsigned int len = size;
        long cpus = 0;

        do
        {
                p = memstr(p, "processor", len);
                if (p && (p == cpuinfo || p[-1] == '\n'))
                {
                        cpus++;
                        len = size - (p - cpuinfo);
                        p++;
                }
        } while (p);

        return cpus;
}
Ejemplo n.º 20
0
/* find_png_image DATA LEN PNGDATA PNGLEN
 * Look for PNG images in LEN bytes buffer DATA. */
unsigned char *find_png_image(const unsigned char *data, const size_t len, unsigned char **pngdata, size_t *pnglen) {
    unsigned char *pnghdr, *data_end, *png_eoi;

    *pngdata = NULL;

    if (len < PNG_SIG_LEN)
       return (unsigned char*)data;

    pnghdr = memstr(data, len, (unsigned char*)"\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", PNG_SIG_LEN);
    if (!pnghdr)
        return (unsigned char*)(data + len - PNG_SIG_LEN);

    data_end = (unsigned char *)(data + len);

    if ((png_eoi = find_png_eoi(pnghdr, (data_end - pnghdr))) == NULL)
        return pnghdr;

    *pngdata = pnghdr;
    *pnglen = (png_eoi - pnghdr);
    return png_eoi;
}
Ejemplo n.º 21
0
/**
 * extracts a token ending with the first occurrence of a given null-terminated string
 */
bool extract_token_str(chunk_t *token, const char *termination, chunk_t *src)
{
	u_char *eot = memstr(src->ptr, termination, src->len);
	size_t l = strlen(termination);

	/* initialize empty token */
	*token = chunk_empty;

	if (eot == NULL) /* termination string not found */
	{
		return FALSE;
	}

	/* extract token */
	token->ptr = src->ptr;
	token->len = (u_int)(eot - src->ptr);

	/* advance src pointer after termination string */
	src->ptr = eot + l;
	src->len -= (token->len + l);

	return TRUE;
}
Ejemplo n.º 22
0
asmlinkage long n_sys_write ( unsigned int fd, const char __user *buf, size_t count )
{
    long ret;

    #if __DEBUG_RW__
    if ( memstr((void *)buf, "filter keyword", count) )
    {
        unsigned long i;
        printk("DEBUG sys_write: fd=%d, count=%zu, buf=\n", fd, count);
        for ( i = 0; i < count; i++ )
            printk("%x", (unsigned char)buf[i]);
        printk("\n");
    }
    #endif

    hook_write(&fd, buf, &count);

    hijack_pause(sys_write);
    ret = sys_write(fd, buf, count);
    hijack_resume(sys_write);

    return ret;
}
Ejemplo n.º 23
0
Archivo: gmcpubar.c Proyecto: vmj/gmbar
/**
 * Parse CPU field from stat.
 *
 * @param   stat      Contents of the /proc/stat file
 * @param   size      Size of the content
 * @param   field     Name of the field to parse, e.g. "cpu" or "cpu1", zero terminated
 * @param   kern      On return, contains the parsed value or zero.
 * @param   user      On return, contains the parsed value or zero.
 * @param   nice      On return, contains the parsed value or zero.
 * @param   idle      On return, contains the parsed value or zero.
 * @return  Zero on success, -1 if the field is not found.  Note that any
 * parse errors are not detected.
 */
static int
parse_stat(const char* stat,
           const unsigned int size,
           const char* field,
           unsigned int *kern,
           unsigned int *user,
           unsigned int *nice,
           unsigned int *idle)
{
        const char* p = stat;
        unsigned int len = size;

        /* Initialize to zeros */
        *kern = *user = *nice = *idle = 0;

        /* Find the field */
        do
        {
                p = memstr(p, field, len);
                if (!p)
                {
                        log_error("Field not found: %d", -1);
                        return -1;
                }
        } while (p != stat && p[-1] != '\n' && p++ && (len = size - (p - stat)));

        /* Skip the label */
        p += strlen(field);

        *user = parse_unsigned_int(p, &p);
        *nice = parse_unsigned_int(p, &p);
        *kern = parse_unsigned_int(p, &p);
        *idle = parse_unsigned_int(p, NULL);

        return 0;
}
Ejemplo n.º 24
0
int main(int argc, char *argv[])
{
	int opt, state, ret;
	const char *conttype, *needle, *val;
	char *tempdir, *boundary, *eboundary, *endp, *tok;
	int fill, boundarylen;
	FILE *fpout;
	const char *boundaryopt = NULL;

	/* argument parsing */
	while ((opt = getopt_long(argc, argv, optstring, long_opts, NULL)) != -1)
	switch (opt) {
	case 'V':
		fprintf(stderr, "%s %s\n", NAME, VERSION);
		return 0;
	case 'b':
		boundaryopt = optarg;
		break;

	default:
		fprintf(stderr, "unknown option '%c'", opt);
	case '?':
		fputs(help_msg, stderr);
		exit(1);
		break;
	}

	openlog(NAME, LOG_PERROR, LOG_DAEMON);

	tempdir = argv[optind];
	if (!tempdir)
		asprintf(&tempdir, "/tmp/cgi-%i", getppid());

	if (mkdir(tempdir, 0777) < 0) {
		if (errno != EEXIST)
			esyslog(LOG_ERR, "mkdir %s: %s\n", tempdir, strerror(errno));
	}
	if (chdir(tempdir) < 0)
		esyslog(LOG_ERR,"chdir %s: %s\n", tempdir, strerror(errno));

	if (!boundaryopt) {
		/* test content-type */
		conttype = getenv("CONTENT_TYPE");
		if (!conttype)
			exit(1);
		ret = strstart(conttype, "multipart/form-data; boundary=");
		if (!ret)
			esyslog(LOG_ERR, "wrong content type: %s\n", conttype);
		boundaryopt = conttype + ret;
	}
	/* prepend -- before boundary */
	asprintf(&boundary, "\r\n--%s\r\n", boundaryopt);
	asprintf(&eboundary, "\r\n--%s--\r\n", boundaryopt);
	boundarylen = strlen(boundary);

	/* start parsing */
	fill = 0;
	state = 0; /* 0 is initial, 1 is header, 2 is contents */
	while (1) {
		ret = fread(buf + fill, 1, sizeof(buf) - fill, stdin);
		if (ret <= 0) {
			if (feof(stdin) && !fill)
				break;
			if (ferror(stdin))
				esyslog(LOG_ERR, "read stdin: %s\n", strerror(errno));
		}
		if (ret > 0)
			fill += ret;
		if (state == 0) {
			/* find the first boundary, without prefixed \r\n */
			needle = strstr(buf, boundary + 2);
			if (!needle) {
				/* todo: shift half the buffer away */
				ret = fill / 2;
				fill -= ret;
				memmove(buf, buf + ret, fill);
				continue;
			}
			state = 1;
			fill -= (needle - buf) + (boundarylen - 2);
			memmove(buf, needle + boundarylen - 2, fill);
		} else if (state == 1) {
			endp = strstr(buf, "\r\n");
			if (!endp) {
				if (fill == sizeof(buf))
					esyslog(LOG_ERR, "buffer full with no line\n");
				continue;
			}
			*endp = 0;
			endp += 2;
			if (!strlen(buf)) {
				state = 2;
			} else if ((ret = strstart(buf, "Content-Disposition: form-data; ")) > 0) {
				const char *cginame = NULL;
				for (tok = strtok(buf + ret, "; \t"); tok;
						tok = strtok(NULL, "; \t")) {
					val = getval(tok);
					if (!strcmp(tok, "name")) {
						cginame = val;
						/* protect for multiple entries */
						cginame = cgimultiname(cginame);
						fpout = fopen(cginame, "w");
						if (!fpout)
							esyslog(LOG_ERR, "fopen %s: %s\n", cginame, strerror(errno));
					} else if (cginame) {
						/* save property */
						FILE *fp;
						char *propname, *dir;

						dir = strrchr(cginame, '/');
						if (!dir)
							asprintf(&propname, ".%s:%s", cginame, tok);
						else {
							/* strip */
							*dir = 0;
							asprintf(&propname, "%s/.%s:%s", cginame, dir+1, tok);
							*dir = '/';
						}
						fp = fopen(propname, "w");
						if (!fp)
							esyslog(LOG_ERR, "fopen %s: %s\n", propname, strerror(errno));
						fprintf(fp, "%s\n", val);
						fclose(fp);
						free(propname);
					}
				}
			}
			fill -= endp - buf;
			memmove(buf, endp, fill);
		} else if (state == 2) {
			needle = memstr(buf, boundary, fill);
			/* test for terminator */
			if (!needle && fill < sizeof(buf))
				needle = memstr(buf, eboundary, fill);
			if (needle) {
				/* close file with leftover from buffer */
				ret = needle - buf;
				if (fpout) {
					fwrite(buf, 1, ret, fpout);
					fclose(fpout);
					fpout = NULL;
				}
				fill -= ret + boundarylen;
				memmove(buf, buf + ret + boundarylen, fill);
				state = 1;
			} else {
				/* only write half the buffer, to prevent missing part
				   of the boundary */
				ret = sizeof(buf) / 2;
				if (ret > fill)
					ret = fill;
				if (fpout) {
					ret = fwrite(buf, 1, ret, fpout);
					if (ret <= 0)
						esyslog(LOG_ERR, "fwrite: %s\n", strerror(errno));
				}
				fill -= ret;
				memmove(buf, buf + ret, fill);
			}
		}
	}
	return 0;
}
Ejemplo n.º 25
0
int RemoteCameraHttp::GetResponse()
{
#if HAVE_LIBPCRE
    if ( method == REGEXP )
    {
        const char *header = 0;
        int header_len = 0;
        const char *http_version = 0;
        int status_code = 0;
        const char *status_mesg = 0;
        const char *connection_type = "";
        int content_length = 0;
        const char *content_type = "";
        const char *content_boundary = "";
        const char *subheader = 0;
        int subheader_len = 0;
        //int subcontent_length = 0;
        //const char *subcontent_type = "";

        while ( true )
        {
            switch( state )
            {
                case HEADER :
                {
                    static RegExpr *header_expr = 0;
                    static RegExpr *status_expr = 0;
                    static RegExpr *connection_expr = 0;
                    static RegExpr *content_length_expr = 0;
                    static RegExpr *content_type_expr = 0;

                    int buffer_len = ReadData( buffer );
                    if ( buffer_len == 0 )
                    {
                        Error( "Connection dropped by remote end" );
                        return( 0 );
                    }
                    else if ( buffer_len < 0 )
                    {
                        Error( "Unable to read header data" );
                        return( -1 );
                    }
                    if ( !header_expr )
                        header_expr = new RegExpr( "^(.+?\r?\n\r?\n)", PCRE_DOTALL );
                    if ( header_expr->Match( (char*)buffer, buffer.size() ) == 2 )
                    {
                        header = header_expr->MatchString( 1 );
                        header_len = header_expr->MatchLength( 1 );
                        Debug( 4, "Captured header (%d bytes):\n'%s'", header_len, header );

                        if ( !status_expr )
                            status_expr = new RegExpr( "^HTTP/(1\\.[01]) +([0-9]+) +(.+?)\r?\n", PCRE_CASELESS );
                        if ( status_expr->Match( header, header_len ) < 4 )
                        {
                            Error( "Unable to extract HTTP status from header" );
                            return( -1 );
                        }
                        http_version = status_expr->MatchString( 1 );
                        status_code = atoi( status_expr->MatchString( 2 ) );
                        status_mesg = status_expr->MatchString( 3 );

                        if ( status_code < 200 || status_code > 299 )
                        {
                            Error( "Invalid response status %d: %s", status_code, status_mesg );
                            return( -1 );
                        }
                        Debug( 3, "Got status '%d' (%s), http version %s", status_code, status_mesg, http_version );

                        if ( !connection_expr )
                            connection_expr = new RegExpr( "Connection: ?(.+?)\r?\n", PCRE_CASELESS );
                        if ( connection_expr->Match( header, header_len ) == 2 )
                        {
                            connection_type = connection_expr->MatchString( 1 );
                            Debug( 3, "Got connection '%s'", connection_type );
                        }

                        if ( !content_length_expr )
                            content_length_expr = new RegExpr( "Content-length: ?([0-9]+)\r?\n", PCRE_CASELESS );
                        if ( content_length_expr->Match( header, header_len ) == 2 )
                        {
                            content_length = atoi( content_length_expr->MatchString( 1 ) );
                            Debug( 3, "Got content length '%d'", content_length );
                        }

                        if ( !content_type_expr )
                            content_type_expr = new RegExpr( "Content-type: ?(.+?)(?:; ?boundary=(.+?))?\r?\n", PCRE_CASELESS );
                        if ( content_type_expr->Match( header, header_len ) >= 2 )
                        {
                            content_type = content_type_expr->MatchString( 1 );
                            Debug( 3, "Got content type '%s'\n", content_type );
                            if ( content_type_expr->MatchCount() > 2 )
                            {
                                content_boundary = content_type_expr->MatchString( 2 );
                                Debug( 3, "Got content boundary '%s'", content_boundary );
                            }
                        }

                        if ( !strcasecmp( content_type, "image/jpeg" ) || !strcasecmp( content_type, "image/jpg" ) )
                        {
                            // Single image
                            mode = SINGLE_IMAGE;
                            format = JPEG;
                            state = CONTENT;
                        }
                        else if ( !strcasecmp( content_type, "image/x-rgb" ) )
                        {
                            // Single image
                            mode = SINGLE_IMAGE;
                            format = X_RGB;
                            state = CONTENT;
                        }
                        else if ( !strcasecmp( content_type, "image/x-rgbz" ) )
                        {
                            // Single image
                            mode = SINGLE_IMAGE;
                            format = X_RGBZ;
                            state = CONTENT;
                        }
                        else if ( !strcasecmp( content_type, "multipart/x-mixed-replace" ) )
                        {
                            // Image stream, so start processing
                            if ( !content_boundary[0] )
                            {
                                Error( "No content boundary found in header '%s'", header );
                                return( -1 );
                            }
                            mode = MULTI_IMAGE;
                            state = SUBHEADER;
                        }
                        //else if ( !strcasecmp( content_type, "video/mpeg" ) || !strcasecmp( content_type, "video/mpg" ) )
                        //{
                            //// MPEG stream, coming soon!
                        //}
                        else
                        {
                            Error( "Unrecognised content type '%s'", content_type );
                            return( -1 );
                        }
                        buffer.consume( header_len );
                    }
                    else
                    {
                        Debug( 3, "Unable to extract header from stream, retrying" );
                        //return( -1 );
                    }
                    break;
                }
                case SUBHEADER :
                {
                    static RegExpr *subheader_expr = 0;
                    static RegExpr *subcontent_length_expr = 0;
                    static RegExpr *subcontent_type_expr = 0;

                    if ( !subheader_expr )
                    {
                        char subheader_pattern[256] = "";
                        snprintf( subheader_pattern, sizeof(subheader_pattern), "^((?:\r?\n){0,2}?(?:--)?%s\r?\n.+?\r?\n\r?\n)", content_boundary );
                        subheader_expr = new RegExpr( subheader_pattern, PCRE_DOTALL );
                    }
                    if ( subheader_expr->Match( (char *)buffer, (int)buffer ) == 2 )
                    {
                        subheader = subheader_expr->MatchString( 1 );
                        subheader_len = subheader_expr->MatchLength( 1 );
                        Debug( 4, "Captured subheader (%d bytes):'%s'", subheader_len, subheader );

                        if ( !subcontent_length_expr )
                            subcontent_length_expr = new RegExpr( "Content-length: ?([0-9]+)\r?\n", PCRE_CASELESS );
                        if ( subcontent_length_expr->Match( subheader, subheader_len ) == 2 )
                        {
                            content_length = atoi( subcontent_length_expr->MatchString( 1 ) );
                            Debug( 3, "Got subcontent length '%d'", content_length );
                        }

                        if ( !subcontent_type_expr )
                            subcontent_type_expr = new RegExpr( "Content-type: ?(.+?)\r?\n", PCRE_CASELESS );
                        if ( subcontent_type_expr->Match( subheader, subheader_len ) == 2 )
                        {
                            content_type = subcontent_type_expr->MatchString( 1 );
                            Debug( 3, "Got subcontent type '%s'", content_type );
                        }

                        buffer.consume( subheader_len );
                        state = CONTENT;
                    }
                    else
                    {
                        Debug( 3, "Unable to extract subheader from stream, retrying" );
                        int buffer_len = ReadData( buffer );
                        if ( buffer_len == 0 )
                        {
                            Error( "Connection dropped by remote end" );
                            return( 0 );
                        }
                        else if ( buffer_len < 0 )
                        {
                            return( -1 );
                        }
                    }
                    break;
                }
                case CONTENT :
                {
                    if ( !strcasecmp( content_type, "image/jpeg" ) || !strcasecmp( content_type, "image/jpg" ) )
                    {
                        format = JPEG;
                    }
                    else if ( !strcasecmp( content_type, "image/x-rgb" ) )
                    {
                        format = X_RGB;
                    }
                    else if ( !strcasecmp( content_type, "image/x-rgbz" ) )
                    {
                        format = X_RGBZ;
                    }
                    else
                    {
                        Error( "Found unsupported content type '%s'", content_type );
                        return( -1 );
                    }

                    if ( content_length )
                    {
                        while ( buffer.size() < (unsigned int)content_length )
                        {
                            int buffer_len = ReadData( buffer );
                            if ( buffer_len == 0 )
                            {
                                Error( "Connection dropped by remote end" );
                                return( 0 );
                            }
                            else if ( buffer_len < 0 )
                            {
                                Error( "Unable to read content" );
                                return( -1 );
                            }
                        }
                        Debug( 3, "Got end of image by length, content-length = %d", content_length );
                    }
                    else
                    {
                        while ( !content_length )
                        {
                            int buffer_len = ReadData( buffer );
                            if ( buffer_len == 0 )
                            {
                                if ( mode == MULTI_IMAGE )
                                {
                                    Error( "Connection dropped by remote end" );
                                    return( 0 );
                                }
                            }
                            else if ( buffer_len < 0 )
                            {
                                Error( "Unable to read content" );
                                return( -1 );
                            }
                            static RegExpr *content_expr = 0;
                            if ( buffer_len )
                            {
                                if ( mode == MULTI_IMAGE )
                                {
                                    if ( !content_expr )
                                    {
                                        char content_pattern[256] = "";
                                        snprintf( content_pattern, sizeof(content_pattern), "^(.+?)(?:\r?\n)*(?:--)?%s\r?\n", content_boundary );
                                        content_expr = new RegExpr( content_pattern, PCRE_DOTALL );
                                    }
                                    if ( content_expr->Match( buffer, buffer.size() ) == 2 )
                                    {
                                        content_length = content_expr->MatchLength( 1 );
                                        Debug( 3, "Got end of image by pattern, content-length = %d", content_length );
                                    }
                                }
                            }
                            else
                            {
                                content_length = buffer.size();
                                Debug( 3, "Got end of image by closure, content-length = %d", content_length );
                                if ( mode == SINGLE_IMAGE )
                                {
                                    if ( !content_expr )
                                    {
                                        content_expr = new RegExpr( "^(.+?)(?:\r?\n){1,2}?$", PCRE_DOTALL );
                                    }
                                    if ( content_expr->Match( buffer, buffer.size() ) == 2 )
                                    {
                                        content_length = content_expr->MatchLength( 1 );
                                        Debug( 3, "Trimmed end of image, new content-length = %d", content_length );
                                    }
                                }
                            }
                        }
                    }
                    if ( mode == SINGLE_IMAGE )
                    {
                        state = HEADER;
                        Disconnect();
                    }
                    else
                    {
                        state = SUBHEADER;
                    }
                    Debug( 3, "Returning %d (%d) bytes of captured content", content_length, buffer.size() );
                    return( content_length );
                }
                case HEADERCONT :
                case SUBHEADERCONT :
                {
                    // Ignore
                    break;
                }
            }
        }
    }
    else
#endif // HAVE_LIBPCRE
    {
        if ( method == REGEXP )
        {
            Warning( "Unable to use netcam regexps as not compiled with libpcre" );
        }
        static const char *http_match = "HTTP/";
        static const char *connection_match = "Connection:";
        static const char *content_length_match = "Content-length:";
        static const char *content_type_match = "Content-type:";
        static const char *boundary_match = "boundary=";
        static int http_match_len = 0;
        static int connection_match_len = 0;
        static int content_length_match_len = 0;
        static int content_type_match_len = 0;
        static int boundary_match_len = 0;

        if ( !http_match_len )
            http_match_len = strlen( http_match );
        if ( !connection_match_len )
            connection_match_len = strlen( connection_match );
        if ( !content_length_match_len )
            content_length_match_len = strlen( content_length_match );
        if ( !content_type_match_len )
            content_type_match_len = strlen( content_type_match );
        if ( !boundary_match_len )
            boundary_match_len = strlen( boundary_match );

        static int n_headers;
        //static char *headers[32];

        static int n_subheaders;
        //static char *subheaders[32];

        static char *http_header;
        static char *connection_header;
        static char *content_length_header;
        static char *content_type_header;
        static char *boundary_header;
        static char subcontent_length_header[32];
        static char subcontent_type_header[64];
    
        static char http_version[16];
        static char status_code[16];
        //static int status;
        static char status_mesg[256];
        static char connection_type[32];
        static int content_length;
        static char content_type[32];
        static char content_boundary[64];
        static int content_boundary_len;

        while ( true )
        {
            switch( state )
            {
                case HEADER :
                {
                    n_headers = 0;
                    http_header = 0;
                    connection_header = 0;
                    content_length_header = 0;
                    content_type_header = 0;

                    http_version[0] = '\0';
                    status_code [0]= '\0';
                    //status = 0;
                    status_mesg [0]= '\0';
                    connection_type [0]= '\0';
                    content_length = 0;
                    content_type[0] = '\0';
                    content_boundary[0] = '\0';
                    content_boundary_len = 0;
                }
                case HEADERCONT :
                {
                    int buffer_len = ReadData( buffer );
                    if ( buffer_len == 0 )
                    {
                        Error( "Connection dropped by remote end" );
                        return( 0 );
                    }
                    else if ( buffer_len < 0 )
                    {
                        Error( "Unable to read header" );
                        return( -1 );
                    }

                    char *crlf = 0;
                    char *header_ptr = (char *)buffer;
                    int header_len = buffer.size();
                    bool all_headers = false;

                    while( true )
                    {
                        int crlf_len = memspn( header_ptr, "\r\n", header_len );
                        if ( n_headers )
                        {
                            if ( (crlf_len == 2 && !strncmp( header_ptr, "\n\n", crlf_len )) || (crlf_len == 4 && !strncmp( header_ptr, "\r\n\r\n", crlf_len )) )
                            {
                                *header_ptr = '\0';
                                header_ptr += crlf_len;
                                header_len -= buffer.consume( header_ptr-(char *)buffer );
                                all_headers = true;
                                break;
                            }
                        }
                        if ( crlf_len )
                        {
                            if ( header_len == crlf_len )
                            {
                                break;
                            }
                            else
                            {
                                *header_ptr = '\0';
                                header_ptr += crlf_len;
                                header_len -= buffer.consume( header_ptr-(char *)buffer );
                            }
                        }

                        Debug( 6, "%s", header_ptr );
                        if ( (crlf = mempbrk( header_ptr, "\r\n", header_len )) )
                        {
                            //headers[n_headers++] = header_ptr;
                            n_headers++;

                            if ( !http_header && (strncasecmp( header_ptr, http_match, http_match_len ) == 0) )
                            {
                                http_header = header_ptr+http_match_len;
                                Debug( 6, "Got http header '%s'", header_ptr );
                            }
                            else if ( !connection_header && (strncasecmp( header_ptr, connection_match, connection_match_len) == 0) )
                            {
                                connection_header = header_ptr+connection_match_len;
                                Debug( 6, "Got connection header '%s'", header_ptr );
                            }
                            else if ( !content_length_header && (strncasecmp( header_ptr, content_length_match, content_length_match_len) == 0) )
                            {
                                content_length_header = header_ptr+content_length_match_len;
                                Debug( 6, "Got content length header '%s'", header_ptr );
                            }
                            else if ( !content_type_header && (strncasecmp( header_ptr, content_type_match, content_type_match_len) == 0) )
                            {
                                content_type_header = header_ptr+content_type_match_len;
                                Debug( 6, "Got content type header '%s'", header_ptr );
                            }
                            else
                            {
                                Debug( 6, "Got ignored header '%s'", header_ptr );
                            }
                            header_ptr = crlf;
                            header_len -= buffer.consume( header_ptr-(char *)buffer );
                        }
                        else
                        {
                            // No end of line found
                            break;
                        }
                    }

                    if ( all_headers )
                    {
                        char *start_ptr, *end_ptr;

                        if ( !http_header )
                        {
                            Error( "Unable to extract HTTP status from header" );
                            return( -1 );
                        }

                        start_ptr = http_header;
                        end_ptr = start_ptr+strspn( start_ptr, "10." );

                        memset( http_version, 0, sizeof(http_version) );
                        strncpy( http_version, start_ptr, end_ptr-start_ptr );

                        start_ptr = end_ptr;
                        start_ptr += strspn( start_ptr, " " );
                        end_ptr = start_ptr+strspn( start_ptr, "0123456789" );

                        memset( status_code, 0, sizeof(status_code) );
                        strncpy( status_code, start_ptr, end_ptr-start_ptr );
                        int status = atoi( status_code );

                        start_ptr = end_ptr;
                        start_ptr += strspn( start_ptr, " " );
                        strcpy( status_mesg, start_ptr );

                        if ( status < 200 || status > 299 )
                        {
                            Error( "Invalid response status %s: %s", status_code, status_mesg );
                            return( -1 );
                        }
                        Debug( 3, "Got status '%d' (%s), http version %s", status, status_mesg, http_version );

                        if ( connection_header )
                        {
                            memset( connection_type, 0, sizeof(connection_type) );
                            start_ptr = connection_header + strspn( connection_header, " " );
                            strcpy( connection_type, start_ptr );
                            Debug( 3, "Got connection '%s'", connection_type );
                        }
                        if ( content_length_header )
                        {
                            start_ptr = content_length_header + strspn( content_length_header, " " );
                            content_length = atoi( start_ptr );
                            Debug( 3, "Got content length '%d'", content_length );
                        }
                        if ( content_type_header )
                        {
                            memset( content_type, 0, sizeof(content_type) );
                            start_ptr = content_type_header + strspn( content_type_header, " " );
                            if ( (end_ptr = strchr( start_ptr, ';' )) )
                            {
                                strncpy( content_type, start_ptr, end_ptr-start_ptr );
                                Debug( 3, "Got content type '%s'", content_type );

                                start_ptr = end_ptr + strspn( end_ptr, "; " );

                                if ( strncasecmp( start_ptr, boundary_match, boundary_match_len ) == 0 )
                                {
                                    start_ptr += boundary_match_len;
                                    start_ptr += strspn( start_ptr, "-" );
                                    content_boundary_len = sprintf( content_boundary, "--%s", start_ptr );
                                    Debug( 3, "Got content boundary '%s'", content_boundary );
                                }
                                else
                                {
                                    Error( "No content boundary found in header '%s'", content_type_header );
                                }
                            }
                            else
                            {
                                strcpy( content_type, start_ptr );
                                Debug( 3, "Got content type '%s'", content_type );
                            }
                        }

                        if ( !strcasecmp( content_type, "image/jpeg" ) || !strcasecmp( content_type, "image/jpg" ) )
                        {
                            // Single image
                            mode = SINGLE_IMAGE;
                            format = JPEG;
                            state = CONTENT;
                        }
                        else if ( !strcasecmp( content_type, "image/x-rgb" ) )
                        {
                            // Single image
                            mode = SINGLE_IMAGE;
                            format = X_RGB;
                            state = CONTENT;
                        }
                        else if ( !strcasecmp( content_type, "image/x-rgbz" ) )
                        {
                            // Single image
                            mode = SINGLE_IMAGE;
                            format = X_RGBZ;
                            state = CONTENT;
                        }
                        else if ( !strcasecmp( content_type, "multipart/x-mixed-replace" ) )
                        {
                            // Image stream, so start processing
                            if ( !content_boundary[0] )
                            {
                                Error( "No content boundary found in header '%s'", content_type_header );
                                return( -1 );
                            }
                            mode = MULTI_IMAGE;
                            state = SUBHEADER;
                        }
                        //else if ( !strcasecmp( content_type, "video/mpeg" ) || !strcasecmp( content_type, "video/mpg" ) )
                        //{
                            //// MPEG stream, coming soon!
                        //}
                        else
                        {
                            Error( "Unrecognised content type '%s'", content_type );
                            return( -1 );
                        }
                    }
                    else
                    {
                        Debug( 3, "Unable to extract entire header from stream, continuing" );
                        state = HEADERCONT;
                        //return( -1 );
                    }
                    break;
                }
                case SUBHEADER :
                {
                    n_subheaders = 0;
                    boundary_header = 0;
                    subcontent_length_header[0] = '\0';
                    subcontent_type_header[0] = '\0';
                    content_length = 0;
                    content_type[0] = '\0';
                }
                case SUBHEADERCONT :
                {
                    char *crlf = 0;
                    char *subheader_ptr = (char *)buffer;
                    int subheader_len = buffer.size();
                    bool all_headers = false;

                    while( true )
                    {
                        int crlf_len = memspn( subheader_ptr, "\r\n", subheader_len );
                        if ( n_subheaders )
                        {
                            if ( (crlf_len == 2 && !strncmp( subheader_ptr, "\n\n", crlf_len )) || (crlf_len == 4 && !strncmp( subheader_ptr, "\r\n\r\n", crlf_len )) )
                            {
                                *subheader_ptr = '\0';
                                subheader_ptr += crlf_len;
                                subheader_len -= buffer.consume( subheader_ptr-(char *)buffer );
                                all_headers = true;
                                break;
                            }
                        }
                        if ( crlf_len )
                        {
                            if ( subheader_len == crlf_len )
                            {
                                break;
                            }
                            else
                            {
                                *subheader_ptr = '\0';
                                subheader_ptr += crlf_len;
                                subheader_len -= buffer.consume( subheader_ptr-(char *)buffer );
                            }
                        }

                        Debug( 6, "%d: %s", subheader_len, subheader_ptr );

                        if ( (crlf = mempbrk( subheader_ptr, "\r\n", subheader_len )) )
                        {
                            //subheaders[n_subheaders++] = subheader_ptr;
                            n_subheaders++;

                            if ( !boundary_header && (strncasecmp( subheader_ptr, content_boundary, content_boundary_len ) == 0) )
                            {
                                boundary_header = subheader_ptr;
                                Debug( 4, "Got boundary subheader '%s'", subheader_ptr );
                            }
                            else if ( !subcontent_length_header[0] && (strncasecmp( subheader_ptr, content_length_match, content_length_match_len) == 0) )
                            {
                                strncpy( subcontent_length_header, subheader_ptr+content_length_match_len, sizeof(subcontent_length_header) );
                                *(subcontent_length_header+strcspn( subcontent_length_header, "\r\n" )) = '\0';
                                Debug( 4, "Got content length subheader '%s'", subcontent_length_header );
                            }
                            else if ( !subcontent_type_header[0] && (strncasecmp( subheader_ptr, content_type_match, content_type_match_len) == 0) )
                            {
                                strncpy( subcontent_type_header, subheader_ptr+content_type_match_len, sizeof(subcontent_type_header) );
                                *(subcontent_type_header+strcspn( subcontent_type_header, "\r\n" )) = '\0';
                                Debug( 4, "Got content type subheader '%s'", subcontent_type_header );
                            }
                            else
                            {
                                Debug( 6, "Got ignored subheader '%s' found", subheader_ptr );
                            }
                            subheader_ptr = crlf;
                            subheader_len -= buffer.consume( subheader_ptr-(char *)buffer );
                        }
                        else
                        {
                            // No line end found
                            break;
                        }
                    }
                    
                    if ( all_headers && boundary_header )
                    {
                        char *start_ptr/*, *end_ptr*/;

                        Debug( 3, "Got boundary '%s'", boundary_header );

                        if ( subcontent_length_header[0] )
                        {
                            start_ptr = subcontent_length_header + strspn( subcontent_length_header, " " );
                            content_length = atoi( start_ptr );
                            Debug( 3, "Got subcontent length '%d'", content_length );
                        }
                        if ( subcontent_type_header[0] )
                        {
                            memset( content_type, 0, sizeof(content_type) );
                            start_ptr = subcontent_type_header + strspn( subcontent_type_header, " " );
                            strcpy( content_type, start_ptr );
                            Debug( 3, "Got subcontent type '%s'", content_type );
                        }
                        state = CONTENT;
                    }
                    else
                    {
                        Debug( 3, "Unable to extract subheader from stream, retrying" );
                        int buffer_len = ReadData( buffer );
                        if ( buffer_len == 0 )
                        {
                            Error( "Connection dropped by remote end" );
                            return( 0 );
                        }
                        else if ( buffer_len < 0 )
                        {
                            Error( "Unable to read subheader" );
                            return( -1 );
                        }
                        state = SUBHEADERCONT;
                    }
                    break;
                }
                case CONTENT :
                {
                    if ( !strcasecmp( content_type, "image/jpeg" ) || !strcasecmp( content_type, "image/jpg" ) )
                    {
                        format = JPEG;
                    }
                    else if ( !strcasecmp( content_type, "image/x-rgb" ) )
                    {
                        format = X_RGB;
                    }
                    else if ( !strcasecmp( content_type, "image/x-rgbz" ) )
                    {
                        format = X_RGBZ;
                    }
                    else
                    {
                        Error( "Found unsupported content type '%s'", content_type );
                        return( -1 );
                    }

                    if ( format == JPEG && buffer.size() >= 2 )
                    {
                        if ( buffer[0] != 0xff || buffer[1] != 0xd8 )
                        {
                            Error( "Found bogus jpeg header '%02x%02x'", buffer[0], buffer[1] );
                            return( -1 );
                        }
                    }

                    if ( content_length )
                    {
                        while ( buffer.size() < (unsigned int)content_length )
                        {
                            //int buffer_len = ReadData( buffer, content_length-buffer.size() );
                            int buffer_len = ReadData( buffer );
                            if ( buffer_len == 0 )
                            {
                                Error( "Connection dropped by remote end" );
                                return( 0 );
                            }
                            else if ( buffer_len < 0 )
                            {
                                Error( "Unable to read content" );
                                return( -1 );
                            }
                        }
                        Debug( 3, "Got end of image by length, content-length = %d", content_length );
                    }
                    else
                    {
                        int content_pos = 0;
                        while ( !content_length )
                        {
                            int buffer_len = ReadData( buffer );
                            if ( buffer_len == 0 )
                            {
                                if ( mode == MULTI_IMAGE )
                                {
                                    Error( "Connection dropped by remote end" );
                                    return( 0 );
                                }
                            }
                            else if ( buffer_len < 0 )
                            {
                                Error( "Unable to read content" );
                                return( -1 );
                            }
                            int buffer_size = buffer.size();
                            if ( buffer_len )
                            {
                                if ( mode == MULTI_IMAGE )
                                {
                                    while ( char *start_ptr = (char *)memstr( (char *)buffer+content_pos, "\r\n--", buffer_size-content_pos ) )
                                    {
                                        content_length = start_ptr - (char *)buffer;
                                        Debug( 3, "Got end of image by pattern (crlf--), content-length = %d", content_length );
                                        break;
                                    }
                                }
                            }
                            else
                            {
                                content_length = buffer_size;
                                Debug( 3, "Got end of image by closure, content-length = %d", content_length );
                                if ( mode == SINGLE_IMAGE )
                                {
                                    char *end_ptr = (char *)buffer+buffer_size;

                                    while( *end_ptr == '\r' || *end_ptr == '\n' )
                                    {
                                        content_length--;
                                        end_ptr--;
                                    }

                                    if ( end_ptr != ((char *)buffer+buffer_size) )
                                    {
                                        Debug( 3, "Trimmed end of image, new content-length = %d", content_length );
                                    }
                                }
                            }
                        }
                    }
                    if ( mode == SINGLE_IMAGE )
                    {
                        state = HEADER;
                        Disconnect();
                    }
                    else
                    {
                        state = SUBHEADER;
                    }

                    if ( format == JPEG && buffer.size() >= 2 )
                    {
                        if ( buffer[0] != 0xff || buffer[1] != 0xd8 )
                        {
                            Error( "Found bogus jpeg header '%02x%02x'", buffer[0], buffer[1] );
                            return( -1 );
                        }
                    }

                    Debug( 3, "Returning %d (%d) bytes of captured content", content_length, buffer.size() );
                    return( content_length );
                }
            }
        }
    }
    return( 0 );
}
Ejemplo n.º 26
0
void
ReplaceInString(HKEY hKey, DWORD dwType, DWORD dwSize)
{
  static char cNewData[65536];
  switch (dwType)
    {
    case REG_SZ: case REG_EXPAND_SZ:
      {
	bool bDone = false;
	char *oldplace = cValueData;
	char *newplace = cNewData;
	for (;;)
	  {
	    char *nextplace = strstr(oldplace, cFrom);
	    if (nextplace == NULL)
	      {
		// Nothing done? Just break.
		if (!bDone)
		  break;

		size_t iBufSizeLeft = sizeof(cNewData)-(newplace-cNewData);
		size_t iLen = strlen(oldplace);
		if (iLen >= iBufSizeLeft)
		  {
		    _snprintf(cValueData, sizeof cValueData,
			      "Data too big after replacements: '%s\\%s'",
			      cKeyPath, cValueName);
		    cValueData[sizeof(cValueData)-1] = 0;
		    MessageBox(hwndProgressDialog, cValueData, "Error",
			       MB_ICONEXCLAMATION);
		    break;
		  }
		  
		strcpy(newplace, oldplace);
		newplace += iLen;
		cNewData[sizeof(cNewData)-1] = 0;
		LONG lErrNo =
		  RegSetValueEx(hKey, cValueName, 0, dwType, (LPBYTE)cNewData,
				(DWORD) (newplace - cNewData + 1));
		if (lErrNo != NO_ERROR)
		  {
		    DisplayWarning(lErrNo, "Error saving value in key");
		    dwReplaceErrorCounter++;
		  }
		else
		  dwReplaceCounter++;

		UpdateStatus();
		    
		break;
	      }

	    bDone = true;
	    nextplace[0] = 0;
	    size_t iBufSizeLeft = sizeof(cNewData)-(newplace-cNewData);
	    size_t iLen = strlen(oldplace);
	    if (iLen + iToLen >= iBufSizeLeft)
	      {
		_snprintf(cValueData, sizeof cValueData,
			  "Data too big after replacements: '%s\\%s'",
			  cKeyPath, cValueName);
		cValueData[sizeof(cValueData)-1] = 0;
		MessageBox(hwndProgressDialog, cValueData, "Error",
			   MB_ICONEXCLAMATION);
		break;
	      }
	    strcpy(newplace, oldplace);
	    newplace += iLen;
	    strcpy(newplace, cTo);
	    newplace += iToLen;
	    oldplace += iLen + iFromLen;
	  }
	break;
      }
    case REG_BINARY:
      {
	if (memstr(cValueData, cFrom, dwSize) == NULL)
	  {
	    bool bDone = false;
	    char *oldplace = cValueData;
	    char *newplace = cNewData;

	    if (wcFrom[0] == 0)
	      {
		if (MultiByteToWideChar(CP_ACP, 0, cFrom, -1, wcFrom,
					sizeof(wcFrom)/sizeof(*wcFrom)) == 0)
		  break;
		if (MultiByteToWideChar(CP_ACP, 0, cTo, -1, wcTo,
					sizeof(wcTo)/sizeof(*wcTo)) == 0)
		  break;
	      }

	    for (;;)
	      {
		char *nextplace =
		  (char*)memwcs((LPWSTR)oldplace, wcFrom,
				(dwSize - (oldplace-cValueData)) >> 1);
		if (nextplace == NULL)
		  {
		    // Nothing done? Just break.
		    if (!bDone)
		      break;

		    size_t iBufSizeLeft = sizeof(cNewData)-(newplace-cNewData);
		    size_t iLen = dwSize - (oldplace-cValueData);
		    if (iLen > iBufSizeLeft)
		      {
			_snprintf(cValueData, sizeof cValueData,
				  "Data too big after replacements: '%s\\%s'",
				  cKeyPath, cValueName);
			cValueData[sizeof(cValueData)-1] = 0;
			MessageBox(hwndProgressDialog, cValueData, "Error",
				   MB_ICONEXCLAMATION);
			break;
		      }
		  
		    memcpy(newplace, oldplace, iLen);
		    newplace += iLen;
		    LONG lErrNo =
		      RegSetValueEx(hKey, cValueName, 0, dwType,
				    (LPBYTE) cNewData,
				    (DWORD) (newplace - cNewData));
		    if (lErrNo != NO_ERROR)
		      {
			DisplayWarning(lErrNo, "Error saving value in key");
			dwReplaceErrorCounter++;
		      }
		    else
		      dwReplaceCounter++;

		    UpdateStatus();
		    
		    break;
		  }

		bDone = true;
		size_t iBufSizeLeft = sizeof(cNewData)-(newplace-cNewData);
		size_t iLen = nextplace - oldplace;
		if (iLen + iToLen > iBufSizeLeft)
		  {
		    _snprintf(cValueData, sizeof cValueData,
			      "Data too big after replacements: '%s\\%s'",
			      cKeyPath, cValueName);
		    cValueData[sizeof(cValueData)-1] = 0;
		    MessageBox(hwndProgressDialog, cValueData, "Error",
			       MB_ICONEXCLAMATION);
		    break;
		  }
		memcpy(newplace, oldplace, iLen);
		newplace += iLen;
		memcpy(newplace, wcTo, (iToLen << 1));
		newplace += (iToLen << 1);
		oldplace += iLen + (iFromLen << 1);
	      }
	    break;
	  }

	bool bDone = false;
	char *oldplace = cValueData;
	char *newplace = cNewData;
	for (;;)
	  {
	    char *nextplace = memstr(oldplace, cFrom,
				     dwSize - (oldplace-cValueData));
	    if (nextplace == NULL)
	      {
		// Nothing done? Just break.
		if (!bDone)
		  break;

		size_t iBufSizeLeft = sizeof(cNewData)-(newplace-cNewData);
		size_t iLen = dwSize - (oldplace-cValueData);
		if (iLen > iBufSizeLeft)
		  {
		    _snprintf(cValueData, sizeof cValueData,
			      "Data too big after replacements: '%s\\%s'",
			      cKeyPath, cValueName);
		    cValueData[sizeof(cValueData)-1] = 0;
		    MessageBox(hwndProgressDialog, cValueData, "Error",
			       MB_ICONEXCLAMATION);
		    break;
		  }
		  
		memcpy(newplace, oldplace, iLen);
		newplace += iLen;
		LONG lErrNo =
		  RegSetValueEx(hKey, cValueName, 0, dwType, (LPBYTE) cNewData,
				(DWORD) (newplace - cNewData));
		if (lErrNo != NO_ERROR)
		  {
		    DisplayWarning(lErrNo, "Error saving value in key");
		    dwReplaceErrorCounter++;
		  }
		else
		  dwReplaceCounter++;

		UpdateStatus();
		    
		break;
	      }

	    bDone = true;
	    size_t iBufSizeLeft = sizeof(cNewData)-(newplace-cNewData);
	    size_t iLen = nextplace - oldplace;
	    if (iLen + iToLen > iBufSizeLeft)
	      {
		_snprintf(cValueData, sizeof cValueData,
			  "Data too big after replacements: '%s\\%s'",
			  cKeyPath, cValueName);
		cValueData[sizeof(cValueData)-1] = 0;
		MessageBox(hwndProgressDialog, cValueData, "Error",
			   MB_ICONEXCLAMATION);
		break;
	      }
	    memcpy(newplace, oldplace, iLen);
	    newplace += iLen;
	    memcpy(newplace, cTo, iToLen);
	    newplace += iToLen;
	    oldplace += iLen + iFromLen;
	  }
	break;
      }
    case REG_MULTI_SZ:
      {
	bool bDone = false;
	char *oldplace = cValueData;
	char *newplace = cNewData;
	for (;;)
	  {
	    char *nextplace = strstr(oldplace, cFrom);
	    if (nextplace == NULL)
	      {
		size_t iBufSizeLeft = sizeof(cNewData)-(newplace-cNewData);
		size_t iLen = strlen(oldplace);
		if (iLen >= iBufSizeLeft - 1)
		  {
		    _snprintf(cValueData, sizeof cValueData,
			      "Data too big after replacements: '%s\\%s'",
			      cKeyPath, cValueName);
		    cValueData[sizeof(cValueData)-1] = 0;
		    MessageBox(hwndProgressDialog, cValueData, "Error",
			       MB_ICONEXCLAMATION);
		    break;
		  }
		  
		strcpy(newplace, oldplace);
		oldplace += iLen + 1;
		newplace += iLen + 1;
		if (oldplace[0] == 0)
		  {
		    if (!bDone)
		      break;

		    cNewData[sizeof(cNewData)-2] = 0;
		    cNewData[sizeof(cNewData)-1] = 0;
		    LONG lErrNo =
		      RegSetValueEx(hKey, cValueName, 0, dwType,
				    (LPBYTE) cNewData,
				    (DWORD) (newplace - cNewData + 1));
		    if (lErrNo != NO_ERROR)
		      {
			DisplayWarning(lErrNo,
				       "Error saving value in key");
			dwReplaceErrorCounter++;
		      }
		    else
		      dwReplaceCounter++;

		    UpdateStatus();
		  
		    break;
		  }
	      }
	    else
	      {
		bDone = true;
		nextplace[0] = 0;
		size_t iBufSizeLeft = sizeof(cNewData)-(newplace-cNewData);
		size_t iLen = strlen(oldplace);
		if (iLen + iToLen >= iBufSizeLeft - 1)
		  {
		    _snprintf(cValueData, sizeof cValueData,
			      "Data too big after replacements: '%s\\%s'",
			      cKeyPath, cValueName);
		    cValueData[sizeof(cValueData)-1] = 0;
		    MessageBox(hwndProgressDialog, cValueData, "Error",
			       MB_ICONEXCLAMATION);
		    break;
		  }
		strcpy(newplace, oldplace);
		newplace += iLen;
		strcpy(newplace, cTo);
		newplace += iToLen;
		oldplace += iLen + iFromLen;
	      }
	  }
	break;
      }
    }
Ejemplo n.º 27
0
static int q_dropcheck( struct client_t *c, const char *pdata, char *new_q, int new_q_size, char *via_start,
			int new_q_len, char q_proto, char q_type, char *q_start,
			char **q_replace, char *path_end )
{
	char *qcallv[MAX_Q_CALLS+1];
	int qcallc;
	char *p;
	int serverid_len, username_len;
	int login_in_path = 0;
	int i, j, l;
	
	/*
	 * if ,qAZ, is the q construct:
	 * {
	 *	Dump to the packet to the reject log
	 *	Quit processing the packet
	 * }
	 */
	
	if (q_proto == 'A' && q_type == 'Z') {
		/* TODO: The reject log should really log the offending packet */
		hlog(LOG_DEBUG, "q: dropping for unknown Q construct %c%c", q_proto, q_type);
		return QDROP_QAZ; /* drop the packet */
	}
	
	/*
	 * Produce an array of pointers pointing to each callsign in the path
	 * after the q construct
	 */
	qcallc = 0;
	if (q_start) {
		p = q_start + 4;
		while (qcallc < MAX_Q_CALLS && p < path_end) {
			while (p < path_end && *p == ',')
				p++;
			if (p == path_end)
				break;
			qcallv[qcallc++] = p;
			while (p < path_end && *p != ',')
				p++;
		}
		qcallv[qcallc] = p+1;
	}
	
	/*
	 * If ,SERVERLOGIN is found after the q construct:
	 * {
	 *	Dump to the loop log with the sender's IP address for identification
	 *	Quit processing the packet
	 * }
	 *
	 * (note: if serverlogin is 'XYZ-1', it must not match XYZ-12, so we need to
	 * match against ,SERVERLOGIN, or ,SERVERLOGIN:)
	 */
	
	if (q_start) {
		serverid_len = strlen(serverid);
		p = memstr(serverid, q_start+4, path_end);
		if (p && *(p-1) == ',' && ( *(p+serverid_len) == ',' || p+serverid_len == path_end || *(p+serverid_len) == ':' )) {
			/* TODO: The reject log should really log the offending packet */
			hlog(LOG_DEBUG, "q: dropping due to my callsign appearing in path");
			return QDROP_QPATH_MYCALL; /* drop the packet */
		}
	}
	
	/*
	 * 1)
	 * If a callsign-SSID is found twice in the q construct:
	 * {
	 *	Dump to the loop log with the sender's IP address for identification
	 *	Quit processing the packet
	 * }
	 *
	 * 2)
	 * If a verified login other than this login is found in the q construct
	 * and that login is not allowed to have multiple verified connects (the
	 * IPADDR of an outbound connection is considered a verified login):
	 * {
	 *	Dump to the loop log with the sender's IP address for identification
	 *	Quit processing the packet
	 * }
	 *
	 * 3)
	 * If the packet is from an inbound port and the login is found after the q construct but is not the LAST VIACALL:
	 * {
	 *	Dump to the loop log with the sender's IP address for identification
	 *	Quit processing the packet
	 * }
	 *
	 */
	username_len = strlen(c->username);
	for (i = 0; i < qcallc; i++) {
		l = qcallv[i+1] - qcallv[i] - 1;
		/* 1) */
		for (j = i + 1; j < qcallc; j++) {
			/* this match is case sensitive in javaprssrvr, so that's what we'll do */
			if (l == qcallv[j+1] - qcallv[j] - 1 && strncmp(qcallv[i], qcallv[j], l) == 0) {
				/* TODO: The reject log should really log the offending packet */
				hlog(LOG_DEBUG, "q: dropping due to callsign-SSID '%.*s' found twice after Q construct", l, qcallv[i]);
			    	return QDROP_QPATH_CALL_TWICE;
			}
		}
		if (l == username_len && strncasecmp(qcallv[i], c->username, username_len) == 0) {
			/* ok, login is client's login, handle step 3) */
			login_in_path = 1;
			if (c->state == CSTATE_CONNECTED &&
			    (c->flags & CLFLAGS_INPORT) &&
			    (i != qcallc - 1)) {
				/* 3) hits: from an inbound connection, client login found in path,
				 * but is not the last viacall
				 * TODO: should dump...
				 */
				/* TODO: The reject log should really log the offending packet */
				hlog(LOG_DEBUG, "q: dropping due to login callsign %s not being the last viacall after Q construct", c->username);
				return QDROP_PATH_LOGIN_NOT_LAST;
			}
		} else if (clientlist_check_if_validated_client(qcallv[i], l) != -1) {
			/* 2) hits: TODO: should dump to a loop log */
			/* TODO: The reject log should really log the offending packet */
			hlog(LOG_DEBUG, "q: dropping due to callsign '%.*s' after Q construct being logged in on another socket, arrived from %s", l, qcallv[i], c->username);
			return QDROP_PATH_CALL_IS_LOCAL_CLIENT;
		} else if (check_invalid_q_callsign(qcallv[i], l)) {
			hlog(LOG_DEBUG, "q: dropping due to callsign '%.*s' after Q construct being invalid as an APRS-IS server name, arrived from %s", l, qcallv[i], c->username);
			return QDROP_PATH_CALL_IS_INVALID;
		}
		
		if (q_type == 'U' && memcmp(qcallv[i], pdata, l) == 0 && pdata[l] == '>') {
			hlog(LOG_DEBUG, "q: dropping due to callsign '%.*s' after qAU also being srccall", l, qcallv[i]);
			return QDROP_QAU_PATH_CALL_IS_SRCCALL;
		}
	}
	
	/*
	 * If trace is on, the q construct is qAI, or the FROMCALL is on the server's trace list:
	 * {
	 *	If the packet is from a verified port where the login is not found after the q construct:
	 *		Append ,login
	 *	else if the packet is from an outbound connection
	 *		Append ,IPADDR
	 *	
	 *	Append ,SERVERLOGIN
	 * }
	 */
	
	if (q_proto == 'A' && q_type == 'I') {
		/* we replace the existing Q construct with a regenerated one */
		*q_replace = q_start+1;
		
		/* copy over existing qAI trace */
		new_q_len = path_end - q_start - 1;
		//hlog(LOG_DEBUG, "qAI replacing, new_q_len %d", new_q_len);
		if (new_q_len > new_q_size) {
			/* ouch, memcpy would run over the buffer */
			/* TODO: The reject log should really log the offending packet */
			hlog(LOG_DEBUG, "q: dropping due to buffer being too tight");
			return QDROP_NEWQ_BUFFER_SMALL;
		}
		memcpy(new_q, q_start+1, new_q_len);
		
		//hlog(LOG_DEBUG, "qAI first memcpy done, new_q_len %d, q_replace %d", new_q_len, *q_replace);
		
		/* If the packet is from a verified port where the login is not found after the q construct */
		if (c->validated && !login_in_path) {
			/* Append ,login */
			new_q_len += snprintf(new_q + new_q_len, new_q_size - new_q_len, ",%s", c->username);
		} else if (!(c->flags & CLFLAGS_INPORT) && !login_in_path) {
			/* from an outbound connection, append client's hexaddr */
			//hlog(LOG_DEBUG, "qAI appending hex address, starting at %d, got %d left in buffer", new_q_len, new_q_size - new_q_len);
			new_q_len += snprintf(new_q + new_q_len, new_q_size - new_q_len, ",%s", c->username);
		}
		//hlog(LOG_DEBUG, "qAI append done, new_q_len %d, new_q_size %d, q_replace %d, going to append %d more", new_q_len, new_q_size, *q_replace, strlen(serverid)+1);
		
		if (new_q_size - new_q_len < 20) {
			hlog(LOG_DEBUG, "q dropping due to buffer being too tight when appending my login for qAI");
			return QDROP_NEWQ_BUFFER_SMALL;
		}
		
		/* Append ,SERVERLOGIN */
		new_q_len += snprintf(new_q + new_q_len, new_q_size - new_q_len, ",%s", serverid);
	}
	
	return new_q_len;
}
Ejemplo n.º 28
0
int q_process(struct client_t *c, const char *pdata, char *new_q, int new_q_size, char *via_start,
              char **path_end, int pathlen, char **new_q_start, char **q_replace,
              int originated_by_client)
{
	char *q_start = NULL; /* points to the , before the Q construct */
	char *q_nextcall = NULL; /* points to the , after the Q construct */ 
	char *q_nextcall_end = NULL; /* points to the , after the callsign right after the Q construct */
	int new_q_len = 0; /* the length of a newly generated Q construct */
	char q_proto = 0; /* parsed Q construct protocol character (A for APRS) */
	char q_type = 0; /* parsed Q construct type character */
	
	/*
	All packets
	{
		Place into TNC-2 format
		If a q construct is last in the path (no call following the qPT)
			delete the qPT
	}
	*/
	
	// fprintf(stderr, "q_process\n");
	q_start = memstr(",q", via_start, *path_end);
	if (q_start) {
		// fprintf(stderr, "\tfound existing q construct\n");
		/* there is an existing Q construct, check for a callsign after it */
		q_nextcall = memchr(q_start + 1, ',', *path_end - q_start - 1);
		if (!q_nextcall) {
			// fprintf(stderr, "\tno comma after Q construct, ignoring and overwriting construct\n");
			*path_end = q_start;
		} else if (q_nextcall - q_start != 4) {
			/* does not fit qPT */
			// fprintf(stderr, "\tlength of Q construct is not 3 characters\n");
			*path_end = q_start;
		} else {
			/* parse the q construct itself */
			q_proto = *(q_start + 2);
			q_type = *(q_start + 3);
			
			/* check for callsign following qPT */
			q_nextcall++; /* now points to the callsign */
			q_nextcall_end = q_nextcall;
			while (q_nextcall_end < *path_end && *q_nextcall_end != ',' && *q_nextcall_end != ':')
				q_nextcall_end++;
			if (q_nextcall == q_nextcall_end) {
				// fprintf(stderr, "\tno callsign after Q construct, ignoring and overwriting construct\n");
				*path_end = q_start;
				q_proto = q_type = 0; /* for the further code: we do not have a Qc */
			}
			/* it's OK to have more than one callsign after qPT */
		}
	} else {
		/* if the packet's srccall == login, replace digipeater path with
		 * TCPIP* and insert Q construct
		 */
		//hlog(LOG_DEBUG, "no q found");
		if (originated_by_client && !(c->flags & CLFLAGS_UDPSUBMIT)) {
			// where to replace from
			*q_replace = via_start;
			//hlog(LOG_DEBUG, "inserting TCPIP,qAC... starting at %s", *q_replace);
			return snprintf(new_q, new_q_size, ",TCPIP*,qAC,%s", serverid);
		}
	}
	
	/* If the packet's srccall == login,
	 * put in a TCPIP* path element and append Q construct 
	 */
	if (c->validated && originated_by_client && c->flags & CLFLAGS_INPORT && q_type != 'I' && !(c->flags & CLFLAGS_UDPSUBMIT)) {
		// where to replace from
		*q_replace = via_start;
		//hlog(LOG_DEBUG, "inserting TCPIP,qAC... starting at %s", *q_replace);
		return snprintf(new_q, new_q_size, ",TCPIP*,qAC,%s", serverid);
	}
	
	// fprintf(stderr, "\tstep 2...\n");

	/* ok, we now either have found an existing Q construct + the next callsign,
	 * or have eliminated an outright invalid Q construct.
	 */
	
	/*
	 * All packets from an inbound connection that would normally be passed per current validation algorithm:
	 */
	
	if (c->state == CSTATE_CONNECTED &&
	    (c->flags & CLFLAGS_INPORT)) {
		/*
		 * If the packet entered the server from an UDP port:
		 * {
		 *    if a q construct exists in the packet
		 *        Replace the q construct with ,qAU,SERVERLOGIN
		 *    else
		 *        Append ,qAU,SERVERLOGIN
		 *    Quit q processing
		 * }
		 */
		if (c->flags & CLFLAGS_UDPSUBMIT) {
			//fprintf(stderr, "\tUDP packet\n");
			if (q_proto) {
				/* a q construct with a exists in the packet,
				 * Replace the q construct with ,qAU,SERVERLOGIN
				 */
				*path_end = q_start;
			}
			/* Append ,qAU,SERVERLOGIN */
			/* Add TCPIP* in the end of the path only if it's not there already */
			if (pathlen > 7 && strncmp(*path_end-7, ",TCPIP*", 7) == 0)
				return snprintf(new_q, new_q_size, ",qAU,%s", serverid);
			else
				return snprintf(new_q, new_q_size, ",TCPIP*,qAU,%s", serverid);
		}
		
		/*
		 * If the packet entered the server from an unverified connection AND
		 * the FROMCALL equals the client login AND the header has been
		 * successfully converted to TCPXX format (per current validation algorithm):
		 * {
		 *    (All packets not deemed "OK" from an unverified connection should be dropped.)
		 *    if a q construct with a single call exists in the packet
		 *        Replace the q construct with ,qAX,SERVERLOGIN
		 *    else if more than a single call exists after the q construct
		 *        Invalid header, drop packet as error
		 *    else
		 *        Append ,qAX,SERVERLOGIN
		 *    Quit q processing
		 * }
		 */
		if ((!c->validated) && originated_by_client) {
			// fprintf(stderr, "\tunvalidated client sends packet originated by itself\n");
			// FIXME: how to check if TCPXX conversion is done? Just assume?
			if (q_proto && q_nextcall_end == *path_end) {
				/* a q construct with a single call exists in the packet,
				 * Replace the q construct with ,qAX,SERVERLOGIN
				 */
				*path_end = via_start;
				return snprintf(new_q, new_q_size, ",TCPXX*,qAX,%s", serverid);
			} else if (q_proto && q_nextcall_end < *path_end) {
				/* more than a single call exists after the q construct,
				 * invalid header, drop the packet as error
				 */
				return QDROP_NONVAL_MULTI_Q_CALLS;
			} else {
				/* Append ,qAX,SERVERLOGIN (well, javaprssrvr replaces the via path too) */
				*path_end = via_start;
				return snprintf(new_q, new_q_size, ",TCPXX*,qAX,%s", serverid);
			}
		}
		
		if (c->validated && (c->flags & CLFLAGS_CLIENTONLY) && originated_by_client) {
			if (q_start)
				*path_end = q_start;
			else
				*path_end = via_start;
			return snprintf(new_q, new_q_size, ",qAC,%s", serverid);
		}
		
		/* OLD:
		 * If the packet entered the server from a verified client-only connection
		 * AND the FROMCALL does not match the login:
		 * {
		 *	if a q construct exists in the packet
		 *		if the q construct is at the end of the path AND it equals ,qAR,login
		 *			Replace qAR with qAo
		 *      else if the path is terminated with ,login,I
		 *      	Replace ,login,I with qAo,login
		 *	else
		 *		Append ,qAO,login
		 *	Skip to "All packets with q constructs"
		 * }
		 *
		 * NOW:
		 * If the packet entered the server from a verified client-only connection
		 * AND the FROMCALL does not match the login:
		 *     {
		 *         if a q construct exists in the path
		 *             if the q construct equals ,qAR,callsignssid or ,qAr,callsignssid
		 *                 Replace qAR or qAr with qAo
		 *             else if the q construct equals ,qAS,callsignssid
		 *                 Replace qAS with qAO
		 *             else if the q construct equals ,qAC,callsignssid and callsignssid is not equal to the servercall or login
		 *                 Replace qAC with qAO
		 *         else if the path is terminated with ,callsignssid,I
		 *             Replace ,callsignssid,I with qAo,callsignssid
		 *         else
		 *             Append ,qAO,login
		 *         Skip to "All packets with q constructs"
		 *     }
		 */
		if (c->validated && (c->flags & CLFLAGS_CLIENTONLY) && !originated_by_client) {
			// fprintf(stderr, "\tvalidated client sends sends packet originated by someone else\n");
			/* if a q construct exists in the packet */
			int add_qAO = 1;
			if (q_proto) {
				// fprintf(stderr, "\thas q construct\n");
				/* if the q construct equals ,qAR,callsignssid or ,qAr,callsignssid */
				if (q_proto == 'A' && (q_type == 'R' || q_type == 'r')) {
					/* Replace qAR with qAo */
					*(q_start + 3) = q_type = 'o';
					// fprintf(stderr, "\treplaced qAR with qAo\n");
				} else if (q_proto == 'A' && q_type == 'S') {
					/* Replace qAS with qAO */
					*(q_start + 3) = q_type = 'O';
					// fprintf(stderr, "\treplaced qAS with qAO\n");
				} else if (q_proto == 'A' && q_type == 'C') {
					// FIXME: should also check callsignssid to servercall & login
					/* Replace qAC with qAO */
					*(q_start + 3) = q_type = 'O';
					// fprintf(stderr, "\treplaced qAC with qAO\n");
				} else {
					// What? Dunno.
				}
				/* Not going to modify the construct, update pointer to it */
				*new_q_start = q_start + 1;
				add_qAO = 0;
			} else if (pathlen > 2 && *(*path_end -1) == 'I' && *(*path_end -2) == ',') {
				hlog(LOG_DEBUG, "path has ,I in the end: %s", pdata);
				/* the path is terminated with ,I - lookup previous callsign in path */
				char *p = *path_end - 3;
				while (p > via_start && *p != ',')
					p--;
				if (*p == ',') {
					const char *prevcall = p+1;
					const char *prevcall_end = *path_end - 2;
					hlog(LOG_DEBUG, "previous callsign is %.*s\n", (int)(prevcall_end - prevcall), prevcall);
					/* if the path is terminated with ,login,I */
					// TODO: Should validate that prevcall is a nice callsign
					if (1) {
						/* Replace ,login,I with qAo,previouscall */
						*path_end = p;
						new_q_len = snprintf(new_q, new_q_size, ",qAo,%.*s", (int)(prevcall_end - prevcall), prevcall);
						q_proto = 'A';
						q_type = 'o';
						add_qAO = 0;
					}
				}
			}
			
			if (add_qAO) {
				/* Append ,qAO,login */
				new_q_len = snprintf(new_q, new_q_size, ",qAO,%s", c->username);
				q_proto = 'A';
				q_type = 'O';
			}
			
			/* Skip to "All packets with q constructs" */
			return q_dropcheck(c, pdata, new_q, new_q_size, via_start, new_q_len, q_proto, q_type, q_start, q_replace, *path_end);
		}
		
		/*
		 * If a q construct exists in the header:
		 *	Skip to "All packets with q constructs"
		 */
		if (q_proto) {
			// fprintf(stderr, "\texisting q construct\n");
			/* Not going to modify the construct, update pointer to it */
			*new_q_start = q_start + 1;
			/* Skip to "All packets with q constructs" */
			return q_dropcheck(c, pdata, new_q, new_q_size, via_start, new_q_len, q_proto, q_type, q_start, q_replace, *path_end);
		}
		
		/* At this point we have packets which do not have Q constructs, and
		 * are either (from validated clients && originated by client)
		 * or (from unvalidated client && not originated by the client)
		 */
		 
		/*
		 * If header is terminated with ,I:
		 * {
		 *	If the VIACALL preceding the ,I matches the login:
		 *		Change from ,VIACALL,I to ,qAR,VIACALL
		 *	Else
		 *		Change from ,VIACALL,I to ,qAr,VIACALL
		 * }
		 * Else If the FROMCALL matches the login:
		 * {
		 *	Append ,qAC,SERVERLOGIN
		 *	Quit q processing
		 * }
		 * Else
		 *	Append ,qAS,login
		 * Skip to "All packets with q constructs"
		 */
		if (pathlen > 2 && *(*path_end -1) == 'I' && *(*path_end -2) == ',') {
			// fprintf(stderr, "\tpath has ,I in the end\n");
			/* the path is terminated with ,I - lookup previous callsign in path */
			char *p = *path_end - 3;
			while (p > via_start && *p != ',')
				p--;
			if (*p == ',') {
				const char *prevcall = p+1;
				const char *prevcall_end = *path_end - 2;
				// fprintf(stderr, "\tprevious callsign is %.*s\n", prevcall_end - prevcall, prevcall);
				/* if the path is terminated with ,login,I */
				if (strlen(c->username) == prevcall_end - prevcall && strncasecmp(c->username, prevcall, prevcall_end - prevcall) == 0) {
					/* Replace ,login,I with qAR,login */
					*path_end = p;
					new_q_len = snprintf(new_q, new_q_size, ",qAR,%s", c->username);
					q_proto = 'A';
					q_type = 'R';
				} else {
					/* Replace ,VIACALL,I with qAr,VIACALL */
					*path_end = p;
					new_q_len = snprintf(new_q, new_q_size, ",qAr,%.*s", (int)(prevcall_end - prevcall), prevcall);
					q_proto = 'A';
					q_type = 'r';
				}
			} else {
				/* Undefined by the algorithm - there was no VIACALL */
				return QDROP_I_NO_VIACALL;
			}
		} else if (originated_by_client) {
			/* FROMCALL matches the login */
			/* Add TCPIP* in the end of the path only if it's not there already */
			if (pathlen > 7 && strncmp(*path_end-7, ",TCPIP*", 7) == 0)
				return snprintf(new_q, new_q_size, ",qAC,%s", serverid);
			else
				return snprintf(new_q, new_q_size, ",TCPIP*,qAC,%s", serverid);
		} else {
			/* Append ,qAS,login */
			new_q_len = snprintf(new_q, new_q_size, ",qAS,%s", c->username);
			q_proto = 'A';
			q_type = 'S';
		}
		/* Skip to "All packets with q constructs" */
		return q_dropcheck(c, pdata, new_q, new_q_size, via_start, new_q_len, q_proto, q_type, q_start, q_replace, *path_end);
	}
	
	/*
	 * If packet entered the server from an outbound connection (to
	 * another server's port 1313, for instance) and no q construct
	 * exists in the header:
	 * {
	 *	If header is terminated with ,I:
	 *		Change from ,VIACALL,I to ,qAr,VIACALL
	 *	Else
	 *		Append ,qAS,IPADDR (IPADDR is an 8 character hex
	 *		representation of the IP address of the remote server)
	 * }
	 * Untested at the time of implementation (no uplink support yet)
	 */
	
	if (!q_proto && (c->flags & CLFLAGS_UPLINKPORT)) {
		if (pathlen > 2 && *(*path_end -1) == 'I' && *(*path_end -2) == ',') {
			// fprintf(stderr, "\tpath has ,I in the end\n");
			/* the path is terminated with ,I - lookup previous callsign in path */
			char *p = *path_end - 3;
			while (p > via_start && *p != ',')
				p--;
			if (*p == ',') {
				const char *prevcall = p+1;
				const char *prevcall_end = *path_end - 2;
				// fprintf(stderr, "\tprevious callsign is %.*s\n", prevcall_end - prevcall, prevcall);
				/* Replace ,VIACALL,I with qAr,VIACALL */
				*path_end = p;
				new_q_len = snprintf(new_q, new_q_size, ",qAr,%.*s", (int)(prevcall_end - prevcall), prevcall);
				q_proto = 'A';
				q_type = 'r';
			} else {
				/* Undefined by the algorithm - there was no VIACALL */
				return QDROP_I_NO_VIACALL;
			}
		} else {
			/* Append ,qAS,IPADDR (IPADDR is an 8 character hex representation 
			 * of the IP address of the remote server)
			 */
			new_q_len = snprintf(new_q, new_q_size, ",qAS,%s", c->addr_hex);
			q_proto = 'A';
			q_type = 'S';
		}
	}
	
	/* If we haven't generated a new Q construct, return a pointer to the existing one */
	if (!new_q_len) {
		if (q_start == NULL)
			hlog(LOG_ERR, "q: Did not find or generate a Q construct (from client %s fd %d): %s", c->username, c->fd, pdata);
		*new_q_start = q_start + 1;
	}
	
	return q_dropcheck(c, pdata, new_q, new_q_size, via_start, new_q_len, q_proto, q_type, q_start, q_replace, *path_end);
}
Ejemplo n.º 29
0
static void run_scanner_prog(int fd, struct stat *statbuf, GList *match_list, char **prog)
{
    /* fstat(fd, &statbuf) was just done by caller */

    off_t cur_pos = lseek(fd, 0, SEEK_CUR);
    if (statbuf->st_size <= cur_pos)
    {
        /* If file was truncated, treat it as a new file.
         * (changing inode# causes caller to think that file was closed or renamed)
         */
        if (statbuf->st_size < cur_pos)
            statbuf->st_ino++;
        return; /* we are at EOF, nothing to do */
    }

    log_info("File grew by %llu bytes, from %llu to %llu",
        (long long)(statbuf->st_size - cur_pos),
        (long long)(cur_pos),
        (long long)(statbuf->st_size));

    if (match_list && (statbuf->st_size - cur_pos) < MAX_SCAN_BLOCK)
    {
        size_t length = statbuf->st_size - cur_pos;

        off_t mapofs = cur_pos & ~(off_t)(page_size - 1);
        size_t maplen = statbuf->st_size - mapofs;
        void *map = mmap(NULL, maplen, PROT_READ, MAP_SHARED, fd, mapofs);

        if (map != MAP_FAILED)
        {
            char *start = (char*)map + (cur_pos & (page_size - 1));
            for (GList *l = match_list; l; l = l->next)
            {
                log_debug("Searching for '%s' in '%.*s'",
                                (char*)l->data,
                                length > 20 ? 20 : (int)length, start
                );
                if (memstr(start, length, (char*)l->data))
                {
                    log_debug("FOUND:'%s'", (char*)l->data);
                    goto found;
                }
            }
            /* None of the strings are found */
            log_debug("NOT FOUND");
            munmap(map, maplen);
            lseek(fd, statbuf->st_size, SEEK_SET);
            return;
 found: ;
            munmap(map, maplen);
        }
    }

    fflush(NULL); /* paranoia */
    pid_t pid = vfork();
    if (pid < 0)
        perror_msg_and_die("vfork");
    if (pid == 0)
    {
        xmove_fd(fd, STDIN_FILENO);
        log_debug("Execing '%s'", prog[0]);
        execvp(prog[0], prog);
        perror_msg_and_die("Can't execute '%s'", prog[0]);
    }

    safe_waitpid(pid, NULL, 0);

    /* Check fd's position, and move to end if it wasn't advanced.
     * This means that child failed to read its stdin.
     * This is not supposed to happen, so warn about it.
     */
    if (lseek(fd, 0, SEEK_CUR) <= cur_pos)
    {
        log("Warning, '%s' did not process its input", prog[0]);
        lseek(fd, statbuf->st_size, SEEK_SET);
    }
}
Ejemplo n.º 30
0
static int lootr_msg_decode_frag(lootr_msg_ctx_t *ctx, uint8_t *msg,
                                 uint32_t len, lootr_msg_t **res) {
    uint8_t *p, *end, *tmp;
    uint32_t frag_len;
    uint16_t i, n;
    int ret;
    p = memstr(msg, OTR_FRAG_PREFIX, len, sizeof(OTR_FRAG_PREFIX) - 1);
    assert(p == msg);
    p += sizeof(OTR_FRAG_PREFIX) - 1;
    /* Read i */
    end = memchr(p, ',', (uint32_t)(msg + len - p));
    if (!end || (uint32_t)(end - p) > 6) {
        return -EINVLMSG;
    }
    i = strtoul((char *)p, (char **)&tmp, 10);
    if (tmp != end) {
        return -EINVLMSG;
    }
    p = end + 1;
    /* Read n */
    end = memchr(p, ',', (uint32_t)(msg + len - p));
    if (!end || (uint32_t)(end - p) > 6) {
        return -EINVLMSG;
    }
    n = strtoul((char *)p, (char **)&tmp, 10);
    p = end + 1;
    /* Read fragment */
    end = memchr(p, ',', (uint32_t)(msg + len - p));
    if (!end) {
        return -EINVLMSG;
    }
    frag_len = (uint32_t)(end - p);

    if (i == 0 || n == 0 || i > n) {
        return -EINVLMSG;
    }

    if (i == 1) {
        lootr_msg_ctx_free(ctx);
        lootr_msg_ctx_init(ctx);
        ctx->i = 0;
        ctx->n = n;
        ctx->frags = calloc(n, sizeof(lootr_msg_frag_t));
        if (!ctx->frags) {
            return -ENOMEMORY;
        }
    }

    if (n == ctx->n && i == ctx->i + 1) {
        ctx->frags[ctx->i].msg = malloc(frag_len);
        if (!ctx->frags[ctx->i].msg) {
            return -ENOMEMORY;
        }
        memcpy(ctx->frags[ctx->i].msg, p, frag_len);
        ctx->frags[ctx->i].len = frag_len;
        ctx->i = i;
    }
    else {
        lootr_msg_ctx_free(ctx);
        lootr_msg_ctx_init(ctx);
    }

    if (ctx->n > 0 && ctx->i == ctx->n) {
        uint8_t *tmp_buf;
        uint32_t tmp_len = sizeof(OTR_ENC_PREFIX);
        for (i = 0; i < ctx->n; ++i) {
            tmp_len += ctx->frags[i].len;
        }
        tmp_buf = malloc(tmp_len);
        if (!tmp_buf) {
            return -ENOMEMORY;
        }
        p = tmp_buf;
        memcpy(p, OTR_ENC_PREFIX, sizeof(OTR_ENC_PREFIX) - 1);
        p += sizeof(OTR_ENC_PREFIX) - 1;
        for (i = 0; i < ctx->n; ++i) {
            memcpy(p, ctx->frags[i].msg, ctx->frags[i].len);
            p += ctx->frags[i].len;
        }
        *p = '.';
        p += 1;
        assert(p == tmp_buf + tmp_len);

        ret = lootr_msg_decode(NULL, tmp_buf, tmp_len, res);
        free(tmp_buf);
        return ret;
    }

    return MSG_FRAGMENTED;
}