tree_cell * nasl_ntlmv2_hash (lex_ctxt * lexic) { const uchar *server_chal = (uchar *) get_str_var_by_name (lexic, "cryptkey"); int sc_len = get_var_size_by_name (lexic, "cryptkey"); const uchar *ntlm_v2_hash = (uchar *) get_str_var_by_name (lexic, "passhash"); int hash_len = get_var_size_by_name (lexic, "passhash"); int client_chal_length = get_int_var_by_name (lexic, "length", -1); tree_cell *retc; unsigned char ntlmv2_response[16]; unsigned char *ntlmv2_client_data = NULL; unsigned char *final_response; int i; if (sc_len < 0 || server_chal == NULL || hash_len < 0 || ntlm_v2_hash == NULL || client_chal_length < 0) { nasl_perror (lexic, "Syntax : ntlmv2_hash(cryptkey:<c>, passhash:<p>, length:<l>)\n"); return NULL; } /* NTLMv2 */ /* We also get to specify some random data */ ntlmv2_client_data = emalloc (client_chal_length); for (i = 0; i < client_chal_length; i++) ntlmv2_client_data[i] = rand () % 256; assert (hash_len == 16); /* Given that data, and the challenge from the server, generate a response */ SMBOWFencrypt_ntv2_ntlmssp(ntlm_v2_hash, server_chal, 8, ntlmv2_client_data, client_chal_length, ntlmv2_response); /* put it into nt_response, for the code below to put into the packet */ final_response = emalloc (client_chal_length + sizeof (ntlmv2_response)); memcpy (final_response, ntlmv2_response, sizeof (ntlmv2_response)); /* after the first 16 bytes is the random data we generated above, so the server can verify us with it */ memcpy (final_response + sizeof (ntlmv2_response), ntlmv2_client_data, client_chal_length); efree (&ntlmv2_client_data); retc = alloc_tree_cell (0, NULL); retc->type = CONST_DATA; retc->size = client_chal_length + sizeof (ntlmv2_response); retc->x.str_val = (char *) final_response; return retc; }
/*---------------------------------------------------------------------*/ tree_cell* nasl_crap(lex_ctxt* lexic) { tree_cell *retc; char *data = get_str_local_var_by_name(lexic, "data"); int data_len = -1; int len = get_int_local_var_by_name(lexic, "length", -1); int len2 = get_int_var_by_num(lexic, 0, -1); if(len < 0 && len2 < 0) { nasl_perror(lexic, "crap: invalid or missing 'length' argument\n"); return NULL; } if (len >= 0 && len2 >= 0) { nasl_perror(lexic, "crap: cannot set both unnamed and named 'length'\n"); return NULL; } if (len < 0) len = len2; if( len == 0 ) return FAKE_CELL; if (data != NULL) { data_len = get_var_size_by_name(lexic, "data"); if (data_len == 0) { nasl_perror(lexic, "crap: invalid null 'data' parameter\n"); return NULL; } } retc = alloc_tree_cell(0, NULL); retc->type = CONST_DATA /*CONST_STR*/; retc->x.str_val = emalloc(len+1); retc->size = len; if (data == NULL) memset(retc->x.str_val, 'X', len); else { int i,r; for(i = 0; i < len - data_len; i += data_len) memcpy(retc->x.str_val + i, data, data_len); if(data_len != 1) { if((r = (len % data_len)) > 0) memcpy(retc->x.str_val + (len - r), data, r); else memcpy(retc->x.str_val + (len - data_len), data, data_len); } else retc->x.str_val[ len - 1 ] = data[0]; } retc->x.str_val[len] = '\0'; return retc; }
tree_cell * nasl_ntlmv1_hash (lex_ctxt * lexic) { const uchar *cryptkey = (uchar *) get_str_var_by_name (lexic, "cryptkey"); char *password = get_str_var_by_name (lexic, "passhash"); int pass_len = get_var_size_by_name (lexic, "passhash"); unsigned char p21[21]; tree_cell *retc; uchar *ret; if (cryptkey == NULL || password == NULL) { nasl_perror (lexic, "Syntax : ntlmv1_hash(cryptkey:<c>, passhash:<p>)\n"); return NULL; } bzero (p21, sizeof (p21)); memcpy (p21, password, pass_len < 16 ? pass_len : 16); ret = emalloc (24); E_P24 (p21, cryptkey, ret); retc = alloc_tree_cell (0, NULL); retc->type = CONST_DATA; retc->size = 24; retc->x.str_val = (char *) ret; return retc; }
tree_cell * nasl_send (lex_ctxt * lexic) { int soc = get_int_local_var_by_name (lexic, "socket", 0); char *data = get_str_local_var_by_name (lexic, "data"); int option = get_int_local_var_by_name (lexic, "option", 0); int length = get_int_local_var_by_name (lexic, "length", 0); int data_length = get_var_size_by_name (lexic, "data"); int n; tree_cell *retc; int type; unsigned int type_len = sizeof (type); if (soc <= 0 || data == NULL) { nasl_perror (lexic, "Syntax error with the send() function\n"); nasl_perror (lexic, "Correct syntax is : send(socket:<soc>, data:<data>\n"); return NULL; } if (length <= 0 || length > data_length) length = data_length; if (!fd_is_stream (soc) && getsockopt (soc, SOL_SOCKET, SO_TYPE, &type, &type_len) == 0 && type == SOCK_DGRAM) { n = send (soc, data, length, option); add_udp_data (lexic->script_infos, soc, data, length); } else n = nsend (soc, data, length, option); retc = alloc_tree_cell (0, NULL); retc->type = CONST_INT; retc->x.i_val = n; return retc; }
/** * @brief Write file */ tree_cell * nasl_file_write (lex_ctxt * lexic) { tree_cell *retc; char *content; int len; int fd; int n; content = get_str_local_var_by_name (lexic, "data"); fd = get_int_local_var_by_name (lexic, "fp", -1); if (content == NULL || fd < 0) { nasl_perror (lexic, "file_write: need two arguments 'fp' and 'data'\n"); return NULL; } len = get_var_size_by_name (lexic, "data"); for (n = 0; n < len;) { int e; errno = 0; e = write (fd, content + n, len - n); if (e < 0 && errno == EINTR) continue; else if (e <= 0) { nasl_perror (lexic, "file_write: write() failed - %s\n", strerror (errno)); break; } else n += e; } retc = alloc_typed_cell (CONST_INT); retc->x.i_val = n; return retc; }
tree_cell * nasl_insert_hexzeros (lex_ctxt * lexic) { const uchar *in = (uchar *) get_str_var_by_name (lexic, "in"); int in_len = get_var_size_by_name (lexic, "in"); char *src; smb_ucs2_t *out, *dst, val; int i; size_t byte_len; tree_cell *retc; if (in_len < 0 || in == NULL) { nasl_perror (lexic, "Syntax : insert_hexzeros(in:<i>)\n"); return NULL; } byte_len = sizeof (smb_ucs2_t) * (strlen ((char *) in) + 1); out = emalloc (byte_len); dst = out; src = (char *) in; for (i = 0; i < in_len; i++) { val = *src; *dst = val; dst++; src++; if (val == 0) break; } /* We don't want null termination */ byte_len = byte_len - 2; retc = alloc_tree_cell (0, NULL); retc->type = CONST_DATA; retc->size = byte_len; retc->x.str_val = (char *) out; return retc; }
/* Does both the NTLMv2 owfs of a user's password */ tree_cell * nasl_ntv2_owf_gen (lex_ctxt * lexic) { const uchar *owf_in = (uchar *) get_str_var_by_name (lexic, "owf"); int owf_in_len = get_var_size_by_name (lexic, "owf"); char *user_in = get_str_var_by_name (lexic, "login"); int user_in_len = get_var_size_by_name (lexic, "login"); char *domain_in = get_str_var_by_name (lexic, "domain"); int domain_len = get_var_size_by_name (lexic, "domain"); char *src_user, *src_domain; smb_ucs2_t *user, *dst_user, val_user; smb_ucs2_t *domain, *dst_domain, val_domain; int i; size_t user_byte_len; size_t domain_byte_len; tree_cell *retc; uchar *kr_buf; HMACMD5Context ctx; if (owf_in_len < 0 || owf_in == NULL || user_in_len < 0 || user_in == NULL || domain_len < 0 || domain_in == NULL) { nasl_perror (lexic, "Syntax : ntv2_owf_gen(owf:<o>, login:<l>, domain:<d>)\n"); return NULL; } assert (owf_in_len == 16); user_byte_len = sizeof (smb_ucs2_t) * (strlen (user_in) + 1); user = emalloc (user_byte_len); dst_user = user; src_user = user_in; for (i = 0; i < user_in_len; i++) { val_user = *src_user; *dst_user = val_user; dst_user++; src_user++; if (val_user == 0) break; } domain_byte_len = sizeof (smb_ucs2_t) * (strlen (domain_in) + 1); domain = emalloc (domain_byte_len); dst_domain = domain; src_domain = domain_in; for (i = 0; i < domain_len; i++) { val_domain = *src_domain; *dst_domain = val_domain; dst_domain++; src_domain++; if (val_domain == 0) break; } strupper_w (user); strupper_w (domain); assert (user_byte_len >= 2); assert (domain_byte_len >= 2); /* We don't want null termination */ user_byte_len = user_byte_len - 2; domain_byte_len = domain_byte_len - 2; kr_buf = emalloc (16); hmac_md5_init_limK_to_64 (owf_in, 16, &ctx); hmac_md5_update ((const unsigned char *) user, user_byte_len, &ctx); hmac_md5_update ((const unsigned char *) domain, domain_byte_len, &ctx); hmac_md5_final (kr_buf, &ctx); efree (&user); efree (&domain); retc = alloc_tree_cell (0, NULL); retc->type = CONST_DATA; retc->size = 16; retc->x.str_val = (char *) kr_buf; return retc; }
/** * @brief Write file */ tree_cell * nasl_fwrite (lex_ctxt * lexic) { tree_cell *retc; char *content, *fname; struct stat lstat_info, fstat_info; int fd; int len, i, x; FILE *fp; content = get_str_local_var_by_name (lexic, "data"); fname = get_str_local_var_by_name (lexic, "file"); if (content == NULL || fname == NULL) { nasl_perror (lexic, "fwrite: need two arguments 'data' and 'file'\n"); return NULL; } len = get_var_size_by_name (lexic, "data"); if (lstat (fname, &lstat_info) == -1) { if (errno != ENOENT) { nasl_perror (lexic, "fwrite: %s: %s\n", fname, strerror (errno)); return NULL; } fd = open (fname, O_WRONLY | O_CREAT | O_EXCL, 0600); if (fd < 0) { nasl_perror (lexic, "fwrite: %s: %s\n", fname, strerror (errno)); return NULL; } } else { fd = open (fname, O_WRONLY | O_CREAT, 0600); if (fd < 0) { nasl_perror (lexic, "fwrite: %s: possible symlink attack!?! %s\n", fname, strerror (errno)); return NULL; } if (fstat (fd, &fstat_info) == -1) { close (fd); nasl_perror (lexic, "fwrite: %s: possible symlink attack!?! %s\n", fname, strerror (errno)); return NULL; } else { if (lstat_info.st_mode != fstat_info.st_mode || lstat_info.st_ino != fstat_info.st_ino || lstat_info.st_dev != fstat_info.st_dev) { close (fd); nasl_perror (lexic, "fwrite: %s: possible symlink attack!?!\n", fname); return NULL; } } } if (ftruncate (fd, 0) == -1) { close (fd); nasl_perror (lexic, "fwrite: %s: %s\n", fname, strerror (errno)); return NULL; } fp = fdopen (fd, "w"); if (fp == NULL) { close (fd); nasl_perror (lexic, "fwrite: %s: %s\n", fname, strerror (errno)); return NULL; } for (i = 0; i < len;) { x = fwrite (content + i, 1, len - i, fp); if (x > 0) i += x; else { nasl_perror (lexic, "fwrite: %s: %s\n", fname, strerror (errno)); (void) fclose (fp); unlink (fname); return NULL; } } if (fclose (fp) < 0) { nasl_perror (lexic, "fwrite: %s: %s\n", fname, strerror (errno)); unlink (fname); return NULL; } retc = alloc_typed_cell (CONST_INT); retc->x.i_val = len; return retc; }
tree_cell* nasl_split(lex_ctxt* lexic) { tree_cell *retc; nasl_array *a; char *p, *str, *sep; int i, i0, j, len, sep_len = 0, keep = 1; anon_nasl_var v; str = get_str_var_by_num(lexic, 0); if (str == NULL) return NULL; len = get_var_size_by_num(lexic, 0); sep = get_str_local_var_by_name(lexic, "sep"); if (sep != NULL) sep_len = get_var_size_by_name(lexic, "sep"); keep = get_int_local_var_by_name(lexic, "keep", 1); retc = alloc_tree_cell(0, NULL); retc->type = DYN_ARRAY; retc->x.ref_val = a = emalloc(sizeof(nasl_array)); bzero(&v, sizeof(v)); v.var_type = VAR2_DATA; if (sep != NULL) { i = 0; j = 0; for(;;) { if ((p = (char*)memmem(str + i, len - i, sep, sep_len)) == NULL) { v.v.v_str.s_siz = len - i; v.v.v_str.s_val = str + i; (void) add_var_to_list(a, j ++, &v); return retc; } else { if (keep) v.v.v_str.s_siz = (p - (str + i)) + sep_len; else v.v.v_str.s_siz = p - (str + i); v.v.v_str.s_val = str + i; (void) add_var_to_list(a, j ++, &v); i = (p - str) + sep_len; if (i >= len) return retc; } } } /* Otherwise, we detect the end of line. A little more subtle */ for (i = i0 = j = 0; i < len; i ++) { if (str[i] == '\r' && str[i+1] == '\n') { i ++; if (keep) v.v.v_str.s_siz = i - i0 + 1; else v.v.v_str.s_siz = i - i0 - 1; v.v.v_str.s_val = str + i0; i0 = i + 1; (void) add_var_to_list(a, j ++, &v); } else if (str[i] == '\n') { if (keep) v.v.v_str.s_siz = i - i0 + 1; else v.v.v_str.s_siz = i - i0; v.v.v_str.s_val = str + i0; i0 = i + 1; (void) add_var_to_list(a, j ++, &v); } } if (i > i0) { v.v.v_str.s_siz = i - i0; v.v.v_str.s_val = str + i0; (void) add_var_to_list(a, j ++, &v); } return retc; }
/* * regex syntax : * * egrep(pattern, string) */ tree_cell * nasl_egrep(lex_ctxt * lexic) { char * pattern = get_str_local_var_by_name(lexic, "pattern"); char * string = get_str_local_var_by_name(lexic, "string"); int icase = get_int_local_var_by_name(lexic, "icase", 0); tree_cell * retc; regex_t re; regmatch_t subs[NS]; char * s, * t; int copt; char * rets; int max_size = get_var_size_by_name(lexic, "string"); if(pattern == NULL || string == NULL) return NULL; bzero(subs, sizeof(subs)); bzero(&re, sizeof(re)); if(icase != 0) copt = REG_ICASE; else copt = 0; rets = emalloc(max_size + 1); string = estrdup(string); s = string; while( s[0] == '\n' )s++; t = strchr(s, '\n'); if(t != NULL ) t[0] = '\0'; if(s[0] != '\0') for(;;) { bzero(&re, sizeof(re)); nasl_re_set_syntax(RE_SYNTAX_POSIX_EGREP); if(nasl_regcomp(&re, pattern, REG_EXTENDED|copt)) { nasl_perror(lexic, "egrep() : regcomp() failed\n"); return NULL; } if(nasl_regexec(&re, s, (size_t)NS, subs, 0) == 0) { char * t = strchr(s, '\n'); if(t != NULL) t[0]='\0'; strcat(rets, s); strcat(rets, "\n"); if(t != NULL) t[0]='\n'; } nasl_regfree(&re); if(t == NULL) s = NULL; else s = &(t[1]); if(s != NULL ) { while(s[0] == '\n') s++; /* Skip empty lines */ t = strchr(s, '\n'); } else t = NULL; if(t != NULL) t[0] = '\0'; if(s == NULL || s[0] == '\0')break; } #ifdef I_WANT_MANY_DIRTY_ERROR_MESSAGES if(rets[0] == '\0') { efree(&rets); efree(&string); return FAKE_CELL; } #endif efree(&string); retc = alloc_tree_cell(0, NULL); retc->type = CONST_DATA; retc->size = strlen(rets); retc->x.str_val = rets; return retc; }