/** * @brief Convert a string into an ISO time string. * @naslfn{isotime_scan} * * * @nasluparam * * - A string * * @naslret A ISO time string on success or NULL on error. * * @param[in] lexic Lexical context of the NASL interpreter. * * @return A tree cell. */ tree_cell * nasl_isotime_scan (lex_ctxt *lexic) { tree_cell *retc; my_isotime_t timebuf; int datalen; const char *string; *timebuf = 0; string = get_str_var_by_num (lexic, 0); if (!string) return NULL; switch (get_var_type_by_num (lexic, 0)) { case VAR2_DATA: datalen = get_var_size_by_num (lexic, 0); if (datalen < ISOTIME_SIZE - 1) return NULL; /* Too short */ memcpy (timebuf, string, ISOTIME_SIZE - 1); timebuf[ISOTIME_SIZE - 1] = 0; string = timebuf; /* FALLTHRU */ case VAR2_STRING: if (!string2isotime (timebuf, string)) return NULL; break; default: return NULL; } retc = alloc_typed_cell (CONST_STR); retc->x.str_val = estrdup (timebuf); retc->size = strlen (timebuf); return retc; }
/** * @brief Check whether an ISO time string is valid * @naslfn{isotime_is_valid} * * * @nasluparam * * - A string. Both, the standard 15 byte string and the better human * readable up to 19 byte format are accepted here. If a plain data * type is is provided only the 15 byte format is accepted. * * @naslret True is this is an ISO string; false if not. * * @param[in] lexic Lexical context of the NASL interpreter. * * @return A tree cell. */ tree_cell * nasl_isotime_is_valid (lex_ctxt *lexic) { int result = 0; tree_cell *retc; my_isotime_t timebuf; const char *string; int datalen; string = get_str_var_by_num (lexic, 0); if (string) { switch (get_var_type_by_num (lexic, 0)) { case VAR2_DATA: datalen = get_var_size_by_num (lexic, 0); if (datalen < ISOTIME_SIZE - 1) break; /* Too short */ memcpy (timebuf, string, ISOTIME_SIZE - 1); timebuf[ISOTIME_SIZE -1] = 0; string = timebuf; /* FALLTHRU */ case VAR2_STRING: if (isotime_p (string) || isotime_human_p (string)) result = 1; break; default: break; } } retc = alloc_typed_cell (CONST_INT); retc->x.i_val = result; return retc; }
tree_cell* nasl_isnull(lex_ctxt* lexic) { int t; tree_cell *retc; t = get_var_type_by_num(lexic, 0); retc = alloc_tree_cell(0, NULL); retc->type = CONST_INT; retc->x.i_val = (t == VAR2_UNDEF); return retc; }
tree_cell* nasl_func_has_arg(lex_ctxt* lexic) { nasl_func *f; char *s; int vt, i, flag = 0; tree_cell *retc; s = get_str_var_by_num(lexic, 0); if (s == NULL) { nasl_perror(lexic, "func_has_arg: missing parameter\n"); return NULL; } f = get_func_ref_by_name(lexic, s); if (f == NULL) { nasl_perror(lexic, "func_args: unknown function \"%s\"\n", s); return NULL; } vt = get_var_type_by_num(lexic, 1); switch(vt) { case VAR2_INT: i = get_int_var_by_num(lexic, 1, -1); if (i >= 0 && i < f->nb_unnamed_args) flag = 1; break; case VAR2_STRING: case VAR2_DATA: s = get_str_var_by_num(lexic, 1); for (i = 0; i < f->nb_named_args && ! flag; i ++) if (strcmp(s, f->args_names[i]) == 0) flag = 1; break; default: nasl_perror(lexic, "func_has_arg: string or integer expected as 2nd parameter\n"); return NULL; } retc = alloc_typed_cell(CONST_INT); retc->x.i_val = flag; return retc; }
/* * Syntax: substr(s, i1) or substr(s, i1, i2) * Returns character from string s starting for position i1 till the end or * position i2 (start of string is 0) */ tree_cell* nasl_substr(lex_ctxt* lexic) { char *s1; int sz1, sz2, i1, i2, typ; tree_cell *retc; s1 = get_str_var_by_num(lexic, 0); sz1 = get_var_size_by_num(lexic, 0); typ = get_var_type_by_num(lexic, 0); i1 = get_int_var_by_num(lexic, 1, -1); #ifndef MAX_INT #define MAX_INT (~(1 << (sizeof(int) * 8 - 1))) #endif i2 = get_int_var_by_num(lexic, 2, MAX_INT); if (i2 > sz1) i2 = sz1-1; if (s1 == NULL || i1 < 0) { nasl_perror(lexic, "Usage: substr(string, idx_start [,idx_end])\n"); return NULL; } retc = alloc_tree_cell(0, NULL); retc->type = (typ == CONST_STR ? CONST_STR : CONST_DATA); if (i1 > i2) { retc->x.str_val = emalloc(0); retc->size = 0; return retc; } sz2 = i2 - i1 + 1; retc->size = sz2; retc->x.str_val = emalloc(sz2); memcpy(retc->x.str_val, s1 + i1, sz2); return retc; }
/** * @brief Get info pertaining to a socket. * @naslfn{get_sock_info} * * This function is used to retrieve various information about an * active socket. It requires the NASL socket number and a string to * select the information to retrieve. * * Supported keywords are: * * - @a dport Return the destination port. This is an integer. NOTE: * Not yet implemented. * * - @a sport Return the source port. This is an integer. NOTE: Not * yet implemented. * * - @a encaps Return the encapsulation of the socket. Example * output: "TLScustom". * * - @a tls-proto Return a string with the actual TLS protocol in use. * n/a" is returned if no SSL/TLS session is active. Example * output: "TLSv1". * * - @a tls-kx Return a string describing the key exchange algorithm. * Example output: "RSA". * * - @a tls-certtype Return the type of the certificate in use by the * session. Example output: "X.509" * * - @a tls-cipher Return the cipher algorithm in use by the session; * Example output: "AES-256-CBC". * * - @a tls-mac Return the message authentication algorithms used by * the session. Example output: "SHA1". * * - @a tls-comp Return the compression algorithms in use by the * session. Example output: "DEFLATE". * * - @a tls-auth Return the peer's authentication type. Example * output: "CERT". * * - @a tls-cert Return the peer's certificates for an SSL or TLS * connection. This is an array of binary strings or NULL if no * certificate is known. * * @nasluparam * * - A NASL socket * * - A string keyword; see above. * * @naslnparam * * - @a asstring If true return a human readable string instead of * an integer. Used only with these keywords: encaps. * * @naslret An integer or a string or NULL on error. * * @param[in] lexic Lexical context of the NASL interpreter. * * @return A tree cell. */ tree_cell * nasl_get_sock_info (lex_ctxt * lexic) { int sock; int type; int err; const char *keyword, *s; tree_cell *retc; int as_string; int transport; gnutls_session_t tls_session; char *strval; int intval; sock = get_int_var_by_num (lexic, 0, -1); if (sock <= 0) { nasl_perror (lexic, "error: socket %d is not valid\n"); return NULL; } keyword = get_str_var_by_num (lexic, 1); if (!keyword || !((type = get_var_type_by_num (lexic, 1)) == VAR2_STRING || type == VAR2_DATA)) { nasl_perror (lexic, "error: second argument is not of type string\n"); return NULL; } as_string = !!get_int_local_var_by_name (lexic, "asstring", 0); transport = 0; strval = NULL; intval = 0; retc = FAKE_CELL; /* Dummy value to detect retc == NULL. */ { void *tmp = NULL; err = get_sock_infos (sock, &transport, &tmp); tls_session = tmp; } if (err) { nasl_perror (lexic, "error retrieving infos for socket %d: %s\n", sock, strerror (err)); retc = NULL; } else if (!strcmp (keyword, "encaps")) { if (as_string) strval = estrdup (get_encaps_name (transport)); else intval = transport; } else if (!strcmp (keyword, "tls-proto")) { if (!tls_session) s = "n/a"; else s = gnutls_protocol_get_name (gnutls_protocol_get_version (tls_session)); strval = estrdup (s?s:"[?]"); } else if (!strcmp (keyword, "tls-kx")) { if (!tls_session) s = "n/a"; else s = gnutls_kx_get_name (gnutls_kx_get (tls_session)); strval = estrdup (s?s:""); } else if (!strcmp (keyword, "tls-certtype")) { if (!tls_session) s = "n/a"; else s = gnutls_certificate_type_get_name (gnutls_certificate_type_get (tls_session)); strval = estrdup (s?s:""); } else if (!strcmp (keyword, "tls-cipher")) { if (!tls_session) s = "n/a"; else s = gnutls_cipher_get_name (gnutls_cipher_get (tls_session)); strval = estrdup (s?s:""); } else if (!strcmp (keyword, "tls-mac")) { if (!tls_session) s = "n/a"; else s = gnutls_mac_get_name (gnutls_mac_get (tls_session)); strval = estrdup (s?s:""); } else if (!strcmp (keyword, "tls-comp")) { if (!tls_session) s = "n/a"; else s = gnutls_compression_get_name (gnutls_compression_get (tls_session)); strval = estrdup (s?s:""); } else if (!strcmp (keyword, "tls-auth")) { if (!tls_session) s = "n/a"; else { switch (gnutls_auth_get_type (tls_session)) { case GNUTLS_CRD_ANON: s = "ANON"; break; case GNUTLS_CRD_CERTIFICATE: s = "CERT"; break; case GNUTLS_CRD_PSK: s = "PSK"; break; case GNUTLS_CRD_SRP: s = "SRP"; break; default: s = "[?]"; break; } } strval = estrdup (s?s:""); } else if (!strcmp (keyword, "tls-cert")) { /* We only support X.509 for now. GNUTLS also allows for OpenPGP, but we are not prepared for that. */ if (!tls_session || gnutls_certificate_type_get (tls_session) != GNUTLS_CRT_X509) s = "n/a"; else { const gnutls_datum_t *list; unsigned int nlist = 0; int i; nasl_array *a; anon_nasl_var v; list = gnutls_certificate_get_peers (tls_session, &nlist); if (!list) retc = NULL; /* No certificate or other error. */ else { retc = alloc_tree_cell (0, NULL); retc->type = DYN_ARRAY; retc->x.ref_val = a = emalloc (sizeof *a); for (i=0; i < nlist; i++) { memset (&v, 0, sizeof v); v.var_type = VAR2_DATA; v.v.v_str.s_val = list[i].data; v.v.v_str.s_siz = list[i].size; add_var_to_list (a, i, &v); } } } } else { nasl_perror (lexic, "unknown keyword '%s'\n", keyword); retc = NULL; } if (!retc) ; else if (retc != FAKE_CELL) ; /* Already allocated. */ else if (strval) { retc = alloc_typed_cell (CONST_STR); retc->x.str_val = strval; retc->size = strlen (strval); } else { retc = alloc_typed_cell (CONST_INT); retc->x.i_val = intval; } return retc; }
tree_cell* nasl_string(lex_ctxt* lexic) { tree_cell *retc; int vi, vn, newlen; int sz, typ; const char *s, *p1; char *p2; retc = alloc_tree_cell(0, NULL); retc->type = CONST_DATA; retc->size = 0; retc->x.str_val = emalloc(0); vn = array_max_index(&lexic->ctx_vars); for (vi = 0; vi < vn; vi ++) { if ((typ = get_var_type_by_num(lexic, vi)) == VAR2_UNDEF) continue; s = get_str_var_by_num(lexic, vi); sz = get_var_size_by_num(lexic, vi); if (sz <= 0) sz = strlen(s); newlen = retc->size + sz; retc->x.str_val = erealloc(retc->x.str_val, newlen + 1); p2 = retc->x.str_val + retc->size; p1 = s; retc->size = newlen; if (typ != VAR2_STRING) { memcpy(p2, p1, sz); p2[sz] = '\0'; } else while (*p1 != '\0') { if(*p1 == '\\' && p1[1] != '\0') { switch (p1[1]) { case 'n': *p2 ++ = '\n'; break; case 't': *p2 ++ = '\t'; break; case 'r': *p2++ = '\r'; break; case '\\': *p2++ = '\\'; break; case 'x': if (isxdigit(p1[2]) && isxdigit(p1[3])) { *p2++ = 16 * (isdigit(p1[2]) ? p1[2]-'0' : 10+tolower(p1[2])-'a') + (isdigit(p1[3]) ? p1[3]-'0' : 10+tolower(p1[3])-'a'); p1 += 2; retc->size -= 2; } else { nasl_perror(lexic, "Buggy hex value '\\x%c%c' skipped\n", isprint(p1[2]) ? p1[2] : '.', isprint(p1[3]) ? p1[3] : '.' ); /* We do not increment p1 by 4, we may miss the end of the string */ } break; default: nasl_perror(lexic, "Unknown%d escape sequence '\\%c'\n", getpid(), isprint(p1[1]) ? p1[1] : '.' ); retc->size --; break; } p1 += 2; retc->size --; } else *p2++ = *p1++; } } retc->x.str_val[retc->size] = '\0'; return retc; }
tree_cell* nasl_rawstring(lex_ctxt* lexic) { tree_cell *retc; int vi, vn, i, j, x; int sz, typ; const char *s; int total_len = 0; retc = alloc_tree_cell(0, NULL); retc->type = CONST_DATA; retc->size = 0; retc->x.str_val = emalloc(RAW_STR_LEN); vn = array_max_index(&lexic->ctx_vars); for (vi = 0; vi < vn && total_len < RAW_STR_LEN-1; vi ++) { if ((typ = get_var_type_by_num(lexic, vi)) == VAR2_UNDEF) continue; sz = get_var_size_by_num(lexic, vi); if (typ == VAR2_INT) { x = get_int_var_by_num(lexic, vi, 0); retc->x.str_val[total_len ++] = x; } else { int current_len = sz; char str[RAW_STR_LEN]; s = get_str_var_by_num(lexic, vi); if (sz <= 0) sz = strlen(s); if (sz >= RAW_STR_LEN) { nasl_perror(lexic, "Error. Too long argument in raw_string()\n"); break; } /* Should we test if the variable is composed only of digits? */ if(typ == VAR2_STRING) { /* TBD:I should decide at last if we keep those "purified" * string or not, and if we do, if "CONST_STR" & "VAR2_STR" are * "not pure" strings */ for(i=0, j=0; i < sz; i++) { if(s[i]=='\\') { if (s[i+1] == 'n') { str[j++]='\n'; i++; } else if (s[i+1] == 't') { str[j++]='\t'; i++; } else if (s[i+1] == 'r') { str[j++] = '\r'; i++; } else if (s[i+1] == 'x' && isxdigit(s[i+2]) && isxdigit(s[i+3])) { x = 0; if(isdigit(s[i+2])) x = (s[i+2]-'0')*16; else x=(10+tolower(s[i+2])-'a')*16; if(isdigit(s[i+3])) x += s[i+3]-'0'; else x += tolower(s[i+3])+10-'a'; str[j++]=x; i+=3; } else if(s[i+1] == '\\') { str[j++] = s[i]; i++; } else i++; } else str[j++] = s[i]; } current_len = j; } else { memcpy(str, s, sz); str[sz] = '\0'; current_len = sz; } if(total_len + current_len > RAW_STR_LEN) { nasl_perror(lexic, "Error. Too long argument in raw_string()\n"); break; } bcopy(str, retc->x.str_val + total_len, current_len); total_len += current_len; } } retc->size = total_len; return retc; }