Exemplo n.º 1
0
static char *fld_tostr(void *rec, uat_field_t *f) {
	guint	    len;
	const char *ptr;
	char       *out;

	f->cb.tostr(rec, &ptr, &len, f->cbdata.tostr, f->fld_data);

	switch(f->mode) {
		case PT_TXTMOD_STRING:
		case PT_TXTMOD_ENUM:
		case PT_TXTMOD_FILENAME:
		case PT_TXTMOD_DIRECTORYNAME:
			out = ep_strndup(ptr, len);
			break;
		case PT_TXTMOD_HEXBYTES: {
			GString *s = g_string_sized_new( len*2 + 1 );
			guint i;

			for (i=0; i<len;i++) g_string_append_printf(s, "%.2X", ((guint8*)ptr)[i]);

			out = ep_strdup(s->str);

			g_string_free(s, TRUE);
			break;
		}
		default:
			g_assert_not_reached();
			out = NULL;
			break;
	}

	return out;
}
Exemplo n.º 2
0
/*
 * Parse the address and port information in a PORT command or in the
 * response to a PASV command.  Return TRUE if we found an address and
 * port, and supply the address and port; return FALSE if we didn't find
 * them.
 *
 * We ignore the IP address in the reply, and use the address from which
 * the request came.
 *
 * XXX - are there cases where they differ?  What if the FTP server is
 * behind a NAT box, so that the address it puts into the reply isn't
 * the address at which you should contact it?  Do all NAT boxes detect
 * FTP PASV replies and rewrite the address?  (I suspect not.)
 *
 * RFC 959 doesn't say much about the syntax of the 227 reply.
 *
 * A proposal from Dan Bernstein at
 *
 *  http://cr.yp.to/ftp/retr.html
 *
 * "recommend[s] that clients use the following strategy to parse the
 * response line: look for the first digit after the initial space; look
 * for the fourth comma after that digit; read two (possibly negative)
 * integers, separated by a comma; the TCP port number is p1*256+p2, where
 * p1 is the first integer modulo 256 and p2 is the second integer modulo
 * 256."
 *
 * wget 1.5.3 looks for a digit, although it doesn't handle negative
 * integers.
 *
 * The FTP code in the source of the cURL library, at
 *
 *  http://curl.haxx.se/lxr/source/lib/ftp.c
 *
 * says that cURL "now scans for a sequence of six comma-separated numbers
 * and will take them as IP+port indicators"; it loops, doing "sscanf"s
 * looking for six numbers separated by commas, stepping the start pointer
 * in the scanf one character at a time - i.e., it tries rather exhaustively.
 *
 * An optimization would be to scan for a digit, and start there, and if
 * the scanf doesn't find six values, scan for the next digit and try
 * again; this will probably succeed on the first try.
 *
 * The cURL code also says that "found reply-strings include":
 *
 *  "227 Entering Passive Mode (127,0,0,1,4,51)"
 *  "227 Data transfer will passively listen to 127,0,0,1,4,51"
 *  "227 Entering passive mode. 127,0,0,1,4,51"
 *
 * so it appears that you can't assume there are parentheses around
 * the address and port number.
 */
static gboolean
parse_port_pasv(const guchar *line, int linelen, guint32 *ftp_ip, guint16 *ftp_port)
{
    char     *args;
    char     *p;
    guchar    c;
    int       i;
    int       ip_address[4], port[2];
    gboolean  ret = FALSE;

    /*
     * Copy the rest of the line into a null-terminated buffer.
     */
    args = ep_strndup(line, linelen);
    p = args;

    for (;;) {
        /*
         * Look for a digit.
         */
        while ((c = *p) != '\0' && !isdigit(c))
            p++;

        if (*p == '\0') {
            /*
             * We ran out of text without finding anything.
             */
            break;
        }

        /*
         * See if we have six numbers.
         */
        i = sscanf(p, "%d,%d,%d,%d,%d,%d",
            &ip_address[0], &ip_address[1], &ip_address[2], &ip_address[3],
            &port[0], &port[1]);
        if (i == 6) {
            /*
             * We have a winner!
             */
            *ftp_port = ((port[0] & 0xFF)<<8) | (port[1] & 0xFF);
            *ftp_ip = g_htonl((ip_address[0] << 24) | (ip_address[1] <<16) | (ip_address[2] <<8) | ip_address[3]);
            ret = TRUE;
            break;
        }

        /*
         * Well, that didn't work.  Skip the first number we found,
         * and keep trying.
         */
        while ((c = *p) != '\0' && isdigit(c))
            p++;
    }

    return ret;
}
Exemplo n.º 3
0
static gboolean
val_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, LogFunc logfunc)
{
	guint32	addr;
	unsigned int nmask_bits;

	const char *has_slash;
	const char *net_str, *addr_str;
	fvalue_t *nmask_fvalue;

	/* Look for CIDR: Is there a single slash in the string? */
	has_slash = strchr(s, '/');
	if (has_slash) {
		/* Make a copy of the string up to but not including the
		 * slash; that's the address portion. */
		addr_str = ep_strndup(s, has_slash - s);
	}
	else {
		addr_str = s;
	}

	if (!get_host_ipaddr(addr_str, &addr)) {
		logfunc("\"%s\" is not a valid hostname or IPv4 address.",
		    addr_str);
		return FALSE;
	}

	ipv4_addr_set_net_order_addr(&(fv->value.ipv4), addr);

	/* If CIDR, get netmask bits. */
	if (has_slash) {
		/* Skip past the slash */
		net_str = has_slash + 1;

		/* XXX - this is inefficient */
		nmask_fvalue = fvalue_from_unparsed(FT_UINT32, net_str, FALSE, logfunc);
		if (!nmask_fvalue) {
			return FALSE;
		}
		nmask_bits = fvalue_get_uinteger(nmask_fvalue);
		FVALUE_FREE(nmask_fvalue);

		if (nmask_bits > 32) {
			logfunc("Netmask bits in a CIDR IPv4 address should be <= 32, not %u",
					nmask_bits);
			return FALSE;
		}
		ipv4_addr_set_netmask_bits(&fv->value.ipv4, nmask_bits);
	}
	else {
		/* Not CIDR; mask covers entire address. */
		ipv4_addr_set_netmask_bits(&(fv->value.ipv4), 32);
	}

	return TRUE;
}
Exemplo n.º 4
0
static gboolean
ipv6_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc)
{
	char *has_slash, *addr_str;
	unsigned int nmask_bits;
	fvalue_t *nmask_fvalue;

	/* Look for prefix: Is there a single slash in the string? */
	if ((has_slash = strchr(s, '/')))
		addr_str = ep_strndup(s, has_slash-s);
	else
		addr_str = s;

	if (!get_host_ipaddr6(addr_str, &(fv->value.ipv6.addr))) {
		logfunc("\"%s\" is not a valid hostname or IPv6 address.", s);
		return FALSE;
	}

	/* If prefix */
	if (has_slash) {
		/* XXX - this is inefficient */
		nmask_fvalue = fvalue_from_unparsed(FT_UINT32, has_slash+1, FALSE, logfunc);
		if (!nmask_fvalue) {
			return FALSE;
		}
		nmask_bits = fvalue_get_uinteger(nmask_fvalue);
		FVALUE_FREE(nmask_fvalue);

		if (nmask_bits > 128) {
			logfunc("Prefix in a IPv6 address should be <= 128, not %u",
					nmask_bits);
			return FALSE;
		}
		fv->value.ipv6.prefix = nmask_bits;
	} else {
		/* Not CIDR; mask covers entire address. */
		fv->value.ipv6.prefix = 128;
	}

	return TRUE;
}
Exemplo n.º 5
0
double asn1_get_real(const guint8 *real_ptr, gint real_len) {
  guint8 octet;
  const guint8 *p;
  guint8 *buf;
  double val = 0;

  if (real_len < 1) return val;
  octet = real_ptr[0];
  p = real_ptr + 1;
  real_len -= 1;
  if (octet & 0x80) {  /* binary encoding */
  } else if (octet & 0x40) {  /* SpecialRealValue */
    switch (octet & 0x3F) {
      case 0x00: val = HUGE_VAL; break;
      case 0x01: val = -HUGE_VAL; break;
    }
  } else {  /* decimal encoding */
    buf = ep_strndup(p, real_len);
    val = atof(buf);
  }

  return val;
}
Exemplo n.º 6
0
static gboolean
parse_extended_pasv_response(const guchar *line, int linelen, guint16 *ftp_port)
{
    int       n;
    char     *args;
    char     *p;
    guchar    c;
    gboolean  ret             = FALSE;
    gboolean  delimiters_seen = FALSE;

    /*
     * Copy the rest of the line into a null-terminated buffer.
     */
    args = ep_strndup(line, linelen);
    p = args;

    /*
     * Look for ( <d> <d> <d>
       (Try to cope with '(' in description)
     */
    for (; !delimiters_seen;) {
        guchar delimiter = '\0';
        while ((c = *p) != '\0' && (c != '('))
            p++;

        if (*p == '\0') {
            return FALSE;
        }

        /* Skip '(' */
        p++;

        /* Make sure same delimiter is used 3 times */
        for (n=0; n<3; n++) {
            if ((c = *p) != '\0') {
                if (delimiter == '\0') {
                    delimiter = c;
                }
                if (c != delimiter) {
                    break;
                }
            p++;
            }
            else {
                break;
            }
        }
        delimiters_seen = TRUE;
    }

    /*
     * Should now be at digits.
     */
    if (*p != '\0') {
        /*
         * We didn't run out of text without finding anything.
         */
        *ftp_port = atoi(p);
        ret = TRUE;
    }

    return ret;
}
Exemplo n.º 7
0
static void
k12_free_cb(void* r)
{
    k12_handles_t* h = r;

    g_free(h->match);
    g_free(h->protos);
    g_free(h->handles);
}


static gboolean
protos_chk_cb(void* r _U_, const char* p, unsigned len, const void* u1 _U_, const void* u2 _U_, const char** err)
{
    gchar** protos;
    gchar* line = ep_strndup(p,len);
    guint num_protos, i;

    g_strstrip(line);
    ascii_strdown_inplace(line);

    protos = ep_strsplit(line,":",0);

    for (num_protos = 0; protos[num_protos]; num_protos++)
        g_strstrip(protos[num_protos]);

    if (!num_protos) {
        *err = ep_strdup_printf("No protocols given");
        return FALSE;
    }
Exemplo n.º 8
0
/*
 * RFC2428 states ....
 *
 *   The first two fields contained in the parenthesis MUST be blank. The   
 *   third field MUST be the string representation of the TCP port number    
 *   on which the server is listening for a data connection. 
 *     
 *   The network protocol used by the data connection will be the same network
 *   protocol used by the control connection. In addition, the network    
 *   address used to establish the data connection will be the same    
 *   network address used for the control connection.
 *     
 *   An example response    string follows:         
 *         
 *       Entering Extended Passive Mode (|||6446|)
 * 
 * ... which in fact means that again both address families IPv4 and IPv6
 * are supported. But gladly it's not necessary to parse because it doesn't
 * occur in EPSV responses. We can leverage ftp_ip_address which is 
 * protocol independent and already set.
 * 
 */
static gboolean
parse_extended_pasv_response(const guchar *line, gint linelen, guint16 *ftp_port,
        guint *pasv_offset, guint *ftp_port_len)
{
    gint       n;
    gchar     *args;
    gchar     *p;
    gchar     *e;
    guchar     c;
    gboolean   ret             = FALSE;
    gboolean   delimiters_seen = FALSE;

    /*
     * Copy the rest of the line into a null-terminated buffer.
     */
    args = ep_strndup(line, linelen);
    p = args;

    /*
     * Look for ( <d> <d> <d>
       (Try to cope with '(' in description)
     */
    for (; !delimiters_seen;) {
        guchar delimiter = '\0';
        while ((c = *p) != '\0' && (c != '('))
            p++;

        if (*p == '\0') {
            return FALSE;
        }

        /* Skip '(' */
        p++;

        /* Make sure same delimiter is used 3 times */
        for (n=0; n<3; n++) {
            if ((c = *p) != '\0') {
                if (delimiter == '\0' && isvalid_rfc2428_delimiter(c)) {
                    delimiter = c;
                }
                if (c != delimiter) {
                    break;
                }
            p++;
            }
            else {
                break;
            }
        }
        delimiters_seen = TRUE;
    }

    /*
     * Should now be at digits.
     */
    if (*p != '\0') {
        /*
         * We didn't run out of text without finding anything.
         */
        *ftp_port = atoi(p);
        *pasv_offset = (guint32)(p - args);

        ret = TRUE;

        /* get port string length */
        if ((e=strchr(p,')')) == NULL) {
            ret = FALSE;
        }
        else {
            *ftp_port_len = (guint)(--e - p);
        }
    }

    return ret;
}
Exemplo n.º 9
0
/*
 * RFC2428 states...
 *
 *     AF Number   Protocol 
 *     ---------   --------         
 *     1           Internet Protocol, Version 4 
 *     2           Internet Protocol, Version 6 
 *     
 *     AF Number   Address Format      Example         
 *     ---------   --------------      -------         
 *     1           dotted decimal      132.235.1.2         
 *     2           IPv6 string         1080::8:800:200C:417A                     
 *                 representations                     
 *                 defined in 
 *     
 *     The following are sample EPRT commands:         
 *          EPRT |1|132.235.1.2|6275|         
 *          EPRT |2|1080::8:800:200C:417A|5282|
 *     
 *     The first command specifies that the server should use IPv4 to open a    
 *     data connection to the host "132.235.1.2" on TCP port 6275.  The    
 *     second command specifies that the server should use the IPv6 network    
 *     protocol and the network address "1080::8:800:200C:417A" to open a    
 *     TCP data connection on port 5282.
 * 
 * ... which means in fact that RFC2428 is capable to handle both, 
 * IPv4 and IPv6 so we have to care about the address family and properly
 * act depending on it.
 * 
 */
static gboolean
parse_eprt_request(const guchar* line, gint linelen, guint32 *eprt_af, 
        guint32 *eprt_ip, guint16 *eprt_ipv6, guint16 *ftp_port, 
        guint32 *eprt_ip_len, guint32 *ftp_port_len) 
{
    gint      delimiters_seen = 0;
    gchar     delimiter;
    gint      fieldlen;
    gchar    *field;
    gint      n;
    gint      lastn;
    char     *args, *p;
    gboolean  ret = TRUE;


    /* line contains the EPRT parameters, we need at least the 4 delimiters */
    if (!line || linelen<4)
        return FALSE;

    /* Copy the rest of the line into a null-terminated buffer. */
    args = ep_strndup(line, linelen);
    p = args;

    /*
     * RFC2428 sect. 2 states ...
     * 
     *     The EPRT command keyword MUST be followed by a single space (ASCII
     *     32). Following the space, a delimiter character (<d>) MUST be
     *     specified.
     *
     * ... the preceding <space> is already stripped so we know that the first
     * character must be the delimiter and has just to be checked to be valid.
     */
    if (!isvalid_rfc2428_delimiter(*p))
        return FALSE;  /* EPRT command does not follow a vaild delimiter;
                        * malformed EPRT command - immediate escape */

    delimiter = *p; 
    /* Validate that the delimiter occurs 4 times in the string */
    for (n = 0; n < linelen; n++) {
        if (*(p+n) == delimiter) 
            delimiters_seen++;
    }
    if (delimiters_seen != 4)
        return FALSE; /* delimiter doesn't occur 4 times 
                       * probably no EPRT request - immediate escape */

    /* we know that the first character is a delimiter... */
    delimiters_seen = 1;
    lastn = 0;
    /* ... so we can start searching from the 2nd onwards */
    for (n=1; n < linelen; n++) {

        if (*(p+n) != delimiter)
            continue;

        /* we found a delimiter */
        delimiters_seen++;

        fieldlen = n - lastn - 1;
        if (fieldlen<=0)
            return FALSE; /* all fields must have data in them */
        field =  p + lastn + 1;

        if (delimiters_seen == 2) {     /* end of address family field */
            gchar *af_str;
            af_str = ep_strndup(field, fieldlen);
            *eprt_af = atoi(af_str);
        }
        else if (delimiters_seen == 3) {/* end of IP address field */
            gchar *ip_str;
            ip_str = ep_strndup(field, fieldlen);

            if (*eprt_af == EPRT_AF_IPv4) {
                if (inet_pton(AF_INET, ip_str, eprt_ip) == 1)
                   ret = TRUE;
                else
                   ret = FALSE;
            }
            else if (*eprt_af == EPRT_AF_IPv6) {
                if (inet_pton(AF_INET6, ip_str, eprt_ipv6) == 1)
                   ret = TRUE;
                else
                   ret = FALSE;
            }
            else
                return FALSE; /* invalid/unknown address family */

            *eprt_ip_len = fieldlen;
        }
        else if (delimiters_seen == 4) {/* end of port field */
            gchar *pt_str;
            pt_str = ep_strndup(field, fieldlen);

            *ftp_port = atoi(pt_str);
            *ftp_port_len = fieldlen;
        }

        lastn = n;
    }

    return ret;
}