int probe_icache_nop(probe_icache_t *cache) { pthread_cond_t cond; dD("NOP"); if (pthread_mutex_lock(&cache->queue_mutex) != 0) { dE("An error ocured while locking the queue mutex: %u, %s", errno, strerror(errno)); return (-1); } if (pthread_cond_init(&cond, NULL) != 0) { dE("Can't initialize icache queue condition variable (NOP): %u, %s", errno, strerror(errno)); return (-1); } if (__probe_icache_add_nolock(cache, NULL, NULL, &cond) != 0) { if (pthread_mutex_unlock(&cache->queue_mutex) != 0) { dE("An error ocured while unlocking the queue mutex: %u, %s", errno, strerror(errno)); abort(); } pthread_cond_destroy(&cond); return (-1); } dD("Signaling `notempty'"); if (pthread_cond_signal(&cache->queue_notempty) != 0) { dE("An error ocured while signaling the `notempty' condition: %u, %s", errno, strerror(errno)); pthread_cond_destroy(&cond); return (-1); } dD("Waiting for icache worker to handle the NOP"); if (pthread_cond_wait(&cond, &cache->queue_mutex) != 0) { dE("An error ocured while waiting for the `NOP' queue condition: %u, %s", errno, strerror(errno)); return (-1); } dD("Sync"); if (pthread_mutex_unlock(&cache->queue_mutex) != 0) { dE("An error ocured while unlocking the queue mutex: %u, %s", errno, strerror(errno)); abort(); } pthread_cond_destroy(&cond); return (0); }
oval_probe_session_t *oval_probe_session_new(struct oval_syschar_model *model) { oval_probe_session_t *sess; void *handler_arg; register size_t i; sess = oscap_talloc(oval_probe_session_t); sess->ph = oval_phtbl_new(); sess->sys_model = model; sess->flg = 0; sess->pext = oval_pext_new(); sess->pext->model = &sess->sys_model; sess->pext->sess_ptr = sess; __init_once(); dD("__probe_meta_count = %zu", OSCAP_GSYM(__probe_meta_count)); for (i = 0; i < OSCAP_GSYM(__probe_meta_count); ++i) { handler_arg = NULL; if (OSCAP_GSYM(__probe_meta)[i].flags & OVAL_PROBEMETA_EXTERNAL) handler_arg = sess->pext; oval_probe_handler_set(sess->ph, OSCAP_GSYM(__probe_meta)[i].otype, OSCAP_GSYM(__probe_meta)[i].handler, handler_arg); } oval_probe_handler_set(sess->ph, OVAL_SUBTYPE_ALL, oval_probe_ext_handler, sess->pext); /* special case for reset */ return(sess); }
static WCHAR *sid_to_trustee_name(SID *sid) { DWORD name_len = 0; DWORD domain_name_len = 0; SID_NAME_USE sid_type; LookupAccountSidW(NULL, sid, NULL, &name_len, NULL, &domain_name_len, &sid_type); WCHAR *name = malloc(name_len * sizeof(WCHAR)); WCHAR *domain_name = malloc(domain_name_len * sizeof(WCHAR)); if (!LookupAccountSidW(NULL, sid, name, &name_len, domain_name, &domain_name_len, &sid_type)) { free(name); free(domain_name); DWORD err = GetLastError(); char *error_message = oscap_windows_error_message(err); dD("LookupAccountSidW failed: %s", error_message); free(error_message); return NULL; } if (*domain_name == L'\0') { free(domain_name); return name; } else { DWORD result_len = name_len + domain_name_len + 2; WCHAR *result = malloc(result_len * sizeof(WCHAR)); swprintf(result, result_len, L"%s\\%s", domain_name, name); free(domain_name); free(name); return result; } return NULL; }
static int get_user_local_groups(WCHAR *user, struct oscap_list *list) { NET_API_STATUS status; LOCALGROUP_USERS_INFO_0 *buffer = NULL; DWORD preffered_max_len = MAX_PREFERRED_LENGTH; DWORD entries_read = 0; DWORD total_entries = 0; /* * LG_INCLUDE_INDIRECT means the function also returns the names of * the local groups in which the user is indirectly a member (that is, * the user has membership in a global group that is itself a member * of one or more local groups). */ status = NetUserGetLocalGroups(NULL, user, 0, LG_INCLUDE_INDIRECT, (LPBYTE *)&buffer, preffered_max_len, &entries_read, &total_entries); if (status != NERR_Success) { dD("NetUserGetLocalGroups failed: %d", status); return 1; } for (DWORD i = 0; i < entries_read; i++) { WCHAR *group_name = buffer[i].lgrui0_name; oscap_list_add(list, wcsdup(group_name)); } NetApiBufferFree(buffer); return 0; }
static const char *ds_sds_session_get_temp_dir(struct ds_sds_session *session) { if (session->temp_dir == NULL) { session->temp_dir = oscap_acquire_temp_dir(); dD("SDS session created temporary directory '%s'.", session->temp_dir); } return session->temp_dir; }
static int ds_sds_dump_component_sce(const xmlNode *script_node, const char *component_id, const char *filename) { if (script_node) { if (oscap_acquire_ensure_parent_dir(filename) < 0) { oscap_seterr(OSCAP_EFAMILY_XML, "Error while creating script parent directory for file '%s' of (id='%s')", filename, component_id); return -1; } // TODO: should we check whether the component is extended? int fd; xmlChar* text_contents = xmlNodeGetContent(script_node); if ((fd = open(filename, O_CREAT | O_TRUNC | O_NOFOLLOW | O_WRONLY, 0700)) < 0) { oscap_seterr(OSCAP_EFAMILY_XML, "Error while creating script component (id='%s') to file '%s'.", component_id, filename); xmlFree(text_contents); return -1; } FILE* output_file = fdopen(fd, "w"); if (output_file == NULL) { oscap_seterr(OSCAP_EFAMILY_XML, "Error while dumping script component (id='%s') to file '%s'.", component_id, filename); xmlFree(text_contents); close(fd); return -1; } // TODO: error checking, fprintf should return strlen((const char*)text_contents) fprintf(output_file, "%s", text_contents ? (char*)text_contents : ""); #ifndef _WIN32 // NB: This code is for SCE scripts if (fchmod(fd, 0700) != 0) { oscap_seterr(OSCAP_EFAMILY_XML, "Failed to set executable permission on script (id='%s') that was split to '%s'.", component_id, filename); } #endif dD("Successfully dumped script component (id='%s') to file '%s'.", component_id, filename); fclose(output_file); xmlFree(text_contents); return 0; } else { oscap_seterr(OSCAP_EFAMILY_XML, "Error while dumping script component (id='%s') to file '%s'. " "The script element was empty!", component_id, filename); return -1; } }
static int get_global_group_members(WCHAR *group_name, struct oscap_list *list) { NET_API_STATUS status; GROUP_USERS_INFO_0 *buffer = NULL; DWORD preffered_max_len = MAX_PREFERRED_LENGTH; DWORD entries_read = 0; DWORD total_entries = 0; DWORD resume_handle = 0; status = NetGroupGetUsers(NULL, group_name, 0, (LPBYTE *)&buffer, preffered_max_len, &entries_read, &total_entries, &resume_handle); if (status != NERR_Success) { dD("NetGroupGetUsers failed: %d", status); return 1; } for (DWORD i = 0; i < entries_read; i++) { WCHAR *member_name = buffer[i].grui0_name; oscap_list_add(list, wcsdup(member_name)); } NetApiBufferFree(buffer); return 0; }
static int get_all_local_groups(struct oscap_list *list) { NET_API_STATUS status; LOCALGROUP_INFO_0 *buffer = NULL; DWORD preffered_max_len = MAX_PREFERRED_LENGTH; DWORD entries_read = 0; DWORD total_entries = 0; DWORD resume_handle = 0; status = NetLocalGroupEnum(NULL, 0, (LPBYTE *)&buffer, preffered_max_len, &entries_read, &total_entries, &resume_handle); if (status != NERR_Success) { dD("NetLocalGroupEnum failed: %d", status); return 1; } for (DWORD i = 0; i < entries_read; i++) { WCHAR *group_name = buffer[i].lgrpi0_name; oscap_list_add(list, wcsdup(group_name)); } NetApiBufferFree(buffer); return 0; }
LowRankVector::LowRankVector(integer Ur, integer Uc, integer Drc, integer Vr, integer Vc) { StieVector dU(Ur, Uc); EucVector dD(Drc, Drc); StieVector dV(Vr, Vc); Element **Elems = new Element *[3]; Elems[0] = &dU; Elems[1] = &dD; Elems[2] = &dV; integer *powsintev = new integer[4]; powsintev[0] = 0; powsintev[1] = 1; powsintev[2] = 2; powsintev[3] = 3; ProductElementInitialization(Elems, 3, powsintev, 3); delete[] powsintev; delete[] Elems; };
// // Interpolates a scale-space extremum's location and scale to subpixel // accuracy to form an image feature. Rejects features with low contrast. // Based on Section 4 of Lowe's paper. static bool adjustLocalExtrema( const vector<Mat>& dog_pyr, KeyPoint& kpt, int octv, int& layer, int& r, int& c, int nOctaveLayers, float contrastThreshold, float edgeThreshold, float sigma ) { const float img_scale = 1.f/(255*SIFT_FIXPT_SCALE); const float deriv_scale = img_scale*0.5f; const float second_deriv_scale = img_scale; const float cross_deriv_scale = img_scale*0.25f; float xi=0, xr=0, xc=0, contr=0; int i = 0; for( ; i < SIFT_MAX_INTERP_STEPS; i++ ) { int idx = octv*(nOctaveLayers+2) + layer; const Mat& img = dog_pyr[idx]; const Mat& prev = dog_pyr[idx-1]; const Mat& next = dog_pyr[idx+1]; Vec3f dD((img.at<sift_wt>(r, c+1) - img.at<sift_wt>(r, c-1))*deriv_scale, (img.at<sift_wt>(r+1, c) - img.at<sift_wt>(r-1, c))*deriv_scale, (next.at<sift_wt>(r, c) - prev.at<sift_wt>(r, c))*deriv_scale); float v2 = (float)img.at<sift_wt>(r, c)*2; float dxx = (img.at<sift_wt>(r, c+1) + img.at<sift_wt>(r, c-1) - v2)*second_deriv_scale; float dyy = (img.at<sift_wt>(r+1, c) + img.at<sift_wt>(r-1, c) - v2)*second_deriv_scale; float dss = (next.at<sift_wt>(r, c) + prev.at<sift_wt>(r, c) - v2)*second_deriv_scale; float dxy = (img.at<sift_wt>(r+1, c+1) - img.at<sift_wt>(r+1, c-1) - img.at<sift_wt>(r-1, c+1) + img.at<sift_wt>(r-1, c-1))*cross_deriv_scale; float dxs = (next.at<sift_wt>(r, c+1) - next.at<sift_wt>(r, c-1) - prev.at<sift_wt>(r, c+1) + prev.at<sift_wt>(r, c-1))*cross_deriv_scale; float dys = (next.at<sift_wt>(r+1, c) - next.at<sift_wt>(r-1, c) - prev.at<sift_wt>(r+1, c) + prev.at<sift_wt>(r-1, c))*cross_deriv_scale; Matx33f H(dxx, dxy, dxs, dxy, dyy, dys, dxs, dys, dss); Vec3f X = H.solve(dD, DECOMP_LU); xi = -X[2]; xr = -X[1]; xc = -X[0]; if( std::abs(xi) < 0.5f && std::abs(xr) < 0.5f && std::abs(xc) < 0.5f ) break; if( std::abs(xi) > (float)(INT_MAX/3) || std::abs(xr) > (float)(INT_MAX/3) || std::abs(xc) > (float)(INT_MAX/3) ) return false; c += cvRound(xc); r += cvRound(xr); layer += cvRound(xi); if( layer < 1 || layer > nOctaveLayers || c < SIFT_IMG_BORDER || c >= img.cols - SIFT_IMG_BORDER || r < SIFT_IMG_BORDER || r >= img.rows - SIFT_IMG_BORDER ) return false; } // ensure convergence of interpolation if( i >= SIFT_MAX_INTERP_STEPS ) return false; { int idx = octv*(nOctaveLayers+2) + layer; const Mat& img = dog_pyr[idx]; const Mat& prev = dog_pyr[idx-1]; const Mat& next = dog_pyr[idx+1]; Matx31f dD((img.at<sift_wt>(r, c+1) - img.at<sift_wt>(r, c-1))*deriv_scale, (img.at<sift_wt>(r+1, c) - img.at<sift_wt>(r-1, c))*deriv_scale, (next.at<sift_wt>(r, c) - prev.at<sift_wt>(r, c))*deriv_scale); float t = dD.dot(Matx31f(xc, xr, xi)); contr = img.at<sift_wt>(r, c)*img_scale + t * 0.5f; if( std::abs( contr ) * nOctaveLayers < contrastThreshold ) return false; // principal curvatures are computed using the trace and det of Hessian float v2 = img.at<sift_wt>(r, c)*2.f; float dxx = (img.at<sift_wt>(r, c+1) + img.at<sift_wt>(r, c-1) - v2)*second_deriv_scale; float dyy = (img.at<sift_wt>(r+1, c) + img.at<sift_wt>(r-1, c) - v2)*second_deriv_scale; float dxy = (img.at<sift_wt>(r+1, c+1) - img.at<sift_wt>(r+1, c-1) - img.at<sift_wt>(r-1, c+1) + img.at<sift_wt>(r-1, c-1)) * cross_deriv_scale; float tr = dxx + dyy; float det = dxx * dyy - dxy * dxy; if( det <= 0 || tr*tr*edgeThreshold >= (edgeThreshold + 1)*(edgeThreshold + 1)*det ) return false; } kpt.pt.x = (c + xc) * (1 << octv); kpt.pt.y = (r + xr) * (1 << octv); kpt.octave = octv + (layer << 8) + (cvRound((xi + 0.5)*255) << 16); kpt.size = sigma*powf(2.f, (layer + xi) / nOctaveLayers)*(1 << octv)*2; kpt.response = std::abs(contr); return true; }
void *probe_signal_handler(void *arg) { probe_t *probe = (probe_t *)arg; siginfo_t siinf; sigset_t siset; #if defined(HAVE_PTHREAD_SETNAME_NP) # if defined(__APPLE__) pthread_setname_np("signal_handler"); # else pthread_setname_np(pthread_self(), "signal_handler"); # endif #endif sigemptyset(&siset); sigaddset(&siset, SIGHUP); sigaddset(&siset, SIGUSR1); sigaddset(&siset, SIGUSR2); sigaddset(&siset, SIGINT); sigaddset(&siset, SIGTERM); sigaddset(&siset, SIGQUIT); sigaddset(&siset, SIGPIPE); #if defined(__linux__) if (prctl(PR_SET_PDEATHSIG, SIGTERM) != 0) dW("prctl(PR_SET_PDEATHSIG, SIGTERM) failed"); #endif dD("Signal handler ready"); switch (errno = pthread_barrier_wait(&OSCAP_GSYM(th_barrier))) { case 0: case PTHREAD_BARRIER_SERIAL_THREAD: break; default: dE("pthread_barrier_wait: %d, %s.", errno, strerror(errno)); return (NULL); } while (sigwaitinfo(&siset, &siinf) != -1) { dD("Received signal %d from %u (%s)", siinf.si_signo, (unsigned int)siinf.si_pid, getppid() == siinf.si_pid ? "parent" : "not my parent"); #if defined(PROBE_SIGNAL_PARENTONLY) /* Listen only to signals sent from the parent process */ if (getppid() != siinf.si_pid) continue; #endif switch(siinf.si_signo) { case SIGUSR1:/* probe abort */ probe->probe_exitcode = ECONNABORTED; /* FALLTHROUGH */ case SIGINT: case SIGTERM: case SIGQUIT: case SIGPIPE: { __thr_collection coll; coll.thr = NULL; coll.cnt = 0; pthread_cancel(probe->th_input); /* collect IDs and cancel threads */ rbt_walk_inorder2(probe->workers, __abort_cb, &coll, 0); /* * Wait till all threads are canceled (they may temporarily disable * cancelability), but at most 60 seconds per thread. */ for (; coll.cnt > 0; --coll.cnt) { probe_worker_t *thr = coll.thr[coll.cnt - 1]; #if defined(HAVE_PTHREAD_TIMEDJOIN_NP) && defined(HAVE_CLOCK_GETTIME) struct timespec j_tm; if (clock_gettime(CLOCK_REALTIME, &j_tm) == -1) { dE("clock_gettime(CLOCK_REALTIME): %d, %s.", errno, strerror(errno)); continue; } j_tm.tv_sec += 60; if ((errno = pthread_timedjoin_np(thr->tid, NULL, &j_tm)) != 0) { dE("[%llu] pthread_timedjoin_np: %d, %s.", (uint64_t)thr->sid, errno, strerror(errno)); /* * Memory will be leaked here by continuing to the next thread. However, we are in the * process of shutting down the whole probe. We're just nice and gave the probe_main() * thread a chance to finish it's critical section which shouldn't take that long... */ continue; } #else if ((errno = pthread_join(thr->tid, NULL)) != 0) { dE("pthread_join: %d, %s.", errno, strerror(errno)); continue; } #endif SEAP_msg_free(coll.thr[coll.cnt - 1]->msg); oscap_free(coll.thr[coll.cnt - 1]); } oscap_free(coll.thr); goto exitloop; } case SIGUSR2: case SIGHUP: /* ignore */ break; } } exitloop: return (NULL); }
void *probe_worker_runfn(void *arg) { probe_pwpair_t *pair = (probe_pwpair_t *)arg; SEXP_t *probe_res, *obj, *oid; int probe_ret; #if defined(HAVE_PTHREAD_SETNAME_NP) pthread_setname_np(pthread_self(), "probe_worker"); #endif dD("handling SEAP message ID %u", pair->pth->sid); // probe_ret = -1; probe_res = pair->pth->msg_handler(pair->probe, pair->pth->msg, &probe_ret); // dD("handler result = %p, return code = %d", probe_res, probe_ret); /* Assuming that the red-black tree API is doing locking for us... */ if (rbt_i32_del(pair->probe->workers, pair->pth->sid, NULL) != 0) { dW("thread not found in the probe thread tree, probably canceled by an external signal"); /* * XXX: this is a possible deadlock; we can't send anything from * here because the signal handler replied to the message */ arg = NULL; SEAP_msg_free(pair->pth->msg); SEXP_free(probe_res); oscap_free(pair); return (NULL); } else { SEXP_t *items; dD("probe thread deleted"); obj = SEAP_msg_get(pair->pth->msg); oid = probe_obj_getattrval(obj, "id"); items = probe_cobj_get_items(probe_res); if (items != NULL) { SEXP_list_sort(items, SEXP_refcmp); SEXP_free(items); } if (probe_rcache_sexp_add(pair->probe->rcache, oid, probe_res) != 0) { /* TODO */ abort(); } SEXP_vfree(obj, oid, NULL); } if (probe_ret != 0) { /* * Something bad happened. A hint of the cause is stored as a error code in * probe_ret (should be). We'll send it to the library using a SEAP error packet. */ if (SEAP_replyerr(pair->probe->SEAP_ctx, pair->probe->sd, pair->pth->msg, probe_ret) == -1) { int ret = errno; dE("An error ocured while sending error status. errno=%u, %s.", errno, strerror(errno)); SEXP_free(probe_res); /* FIXME */ exit(ret); } SEXP_free(probe_res); } else { SEAP_msg_t *seap_reply; /* * OK, the probe actually returned something, let's send it to the library. */ seap_reply = SEAP_msg_new(); SEAP_msg_set(seap_reply, probe_res); if (SEAP_reply(pair->probe->SEAP_ctx, pair->probe->sd, seap_reply, pair->pth->msg) == -1) { int ret = errno; SEAP_msg_free(seap_reply); SEXP_free(probe_res); exit(ret); } SEAP_msg_free(seap_reply); SEXP_free(probe_res); } SEAP_msg_free(pair->pth->msg); oscap_free(pair->pth); oscap_free(pair); pthread_detach(pthread_self()); return (NULL); }
static void *probe_icache_worker(void *arg) { probe_icache_t *cache = (probe_icache_t *)(arg); probe_iqpair_t *pair, pair_mem; SEXP_ID_t item_ID; assume_d(cache != NULL, NULL); pthread_setname_np(pthread_self(), "icache_worker"); if (pthread_mutex_lock(&cache->queue_mutex) != 0) { dE("An error ocured while locking the queue mutex: %u, %s", errno, strerror(errno)); return (NULL); } pair = &pair_mem; dD("icache worker ready"); switch (errno = pthread_barrier_wait(&OSCAP_GSYM(th_barrier))) { case 0: case PTHREAD_BARRIER_SERIAL_THREAD: break; default: dE("pthread_barrier_wait: %d, %s.", errno, strerror(errno)); pthread_mutex_unlock(&cache->queue_mutex); return (NULL); } while(pthread_cond_wait(&cache->queue_notempty, &cache->queue_mutex) == 0) { assume_d(cache->queue_cnt > 0, NULL); next: dD("Extracting item from the cache queue: cnt=%"PRIu16", beg=%"PRIu16"", cache->queue_cnt, cache->queue_beg); /* * Extract an item from the queue and update queue beg, end & cnt */ pair_mem = cache->queue[cache->queue_beg]; #ifndef NDEBUG memset(cache->queue + cache->queue_beg, 0, sizeof(probe_iqpair_t)); #endif --cache->queue_cnt; ++cache->queue_beg; if (cache->queue_beg == cache->queue_max) cache->queue_beg = 0; assume_d(cache->queue_cnt == 0 ? cache->queue_end == cache->queue_beg : cache->queue_end != cache->queue_beg, NULL); /* * Release the mutex */ if (pthread_mutex_unlock(&cache->queue_mutex) != 0) { dE("An error ocured while unlocking the queue mutex: %u, %s", errno, strerror(errno)); abort(); } dD("Signaling `notfull'"); if (pthread_cond_signal(&cache->queue_notfull) != 0) { dE("An error ocured while signaling the `notfull' condition: %u, %s", errno, strerror(errno)); abort(); } if (pair->cobj == NULL) { /* * Handle NOP case (synchronization) */ assume_d(pair->p.cond != NULL, NULL); dD("Handling NOP"); if (pthread_cond_signal(pair->p.cond) != 0) { dE("An error ocured while signaling NOP condition: %u, %s", errno, strerror(errno)); abort(); } } else { probe_citem_t *cached = NULL; dD("Handling cache request"); /* * Compute item ID */ item_ID = SEXP_ID_v(pair->p.item); dD("item ID=%"PRIu64"", item_ID); /* * Perform cache lookup */ if (rbt_i64_get(cache->tree, (int64_t)item_ID, (void *)&cached) == 0) { register uint16_t i; SEXP_t rest1, rest2; /* * Maybe a cache HIT */ dD("cache HIT #1"); for (i = 0; i < cached->count; ++i) { if (SEXP_deepcmp(SEXP_list_rest_r(&rest1, pair->p.item), SEXP_list_rest_r(&rest2, cached->item[i]))) { SEXP_free_r(&rest1); SEXP_free_r(&rest2); break; } SEXP_free_r(&rest1); SEXP_free_r(&rest2); } if (i == cached->count) { /* * Cache MISS */ dD("cache MISS"); cached->item = oscap_realloc(cached->item, sizeof(SEXP_t *) * ++cached->count); cached->item[cached->count - 1] = pair->p.item; /* Assign an unique item ID */ probe_icache_item_setID(pair->p.item, item_ID); } else { /* * Cache HIT */ dD("cache HIT #2 -> real HIT"); SEXP_free(pair->p.item); pair->p.item = cached->item[i]; } } else { /* * Cache MISS */ dD("cache MISS"); cached = oscap_talloc(probe_citem_t); cached->item = oscap_talloc(SEXP_t *); cached->item[0] = pair->p.item; cached->count = 1; /* Assign an unique item ID */ probe_icache_item_setID(pair->p.item, item_ID); if (rbt_i64_add(cache->tree, (int64_t)item_ID, (void *)cached, NULL) != 0) { dE("Can't add item (k=%"PRIi64" to the cache (%p)", (int64_t)item_ID, cache->tree); oscap_free(cached->item); oscap_free(cached); /* now what? */ abort(); } } if (probe_cobj_add_item(pair->cobj, pair->p.item) != 0) { dW("An error ocured while adding the item to the collected object"); } } if (pthread_mutex_lock(&cache->queue_mutex) != 0) { dE("An error ocured while re-locking the queue mutex: %u, %s", errno, strerror(errno)); abort(); } if (cache->queue_cnt > 0) goto next; } return (NULL); }
static int collect_access_rights(probe_ctx *ctx, WCHAR *security_principle, bool include_group, bool resolve_group) { char *security_principle_str = oscap_windows_wstr_to_str(security_principle); LSA_OBJECT_ATTRIBUTES object_attributes; ZeroMemory(&object_attributes, sizeof(LSA_OBJECT_ATTRIBUTES)); LSA_HANDLE lsa_policy_handle; NTSTATUS status = LsaOpenPolicy(NULL, &object_attributes, POLICY_LOOKUP_NAMES, &lsa_policy_handle); if (status != STATUS_SUCCESS) { DWORD err = LsaNtStatusToWinError(status); char *error_message = oscap_windows_error_message(err); dD("LsaOpenPolicy failed for principle '%s': %s", security_principle_str, error_message); free(error_message); free(security_principle_str); return 1; } /* Convert the value of the security_principle element to a SID. */ DWORD sid_len = 0; DWORD domain_name_len = 0; SID_NAME_USE sid_type; LookupAccountNameW(NULL, security_principle, NULL, &sid_len, NULL, &domain_name_len, &sid_type); SID *sid = malloc(sid_len); WCHAR *domain_name = malloc(domain_name_len * sizeof(WCHAR)); if (!LookupAccountNameW(NULL, security_principle, sid, &sid_len, domain_name, &domain_name_len, &sid_type)) { DWORD err = GetLastError(); char *error_message = oscap_windows_error_message(err); dD("LookupAccountNameW failed for '%s': %s", security_principle_str, error_message); free(error_message); free(security_principle_str); free(sid); free(domain_name); return 1; } /* Is it a group? */ if (sid_type == SidTypeGroup || sid_type == SidTypeWellKnownGroup || sid_type == SidTypeAlias) { if (resolve_group) { struct oscap_list *group_members_list = oscap_list_new(); get_local_group_members(security_principle, group_members_list); get_global_group_members(security_principle, group_members_list); struct oscap_iterator *group_members_it = oscap_iterator_new(group_members_list); while (oscap_iterator_has_more(group_members_it)) { WCHAR *group_member = oscap_iterator_next(group_members_it); collect_access_rights(ctx, group_member, include_group, resolve_group); } oscap_iterator_free(group_members_it); oscap_list_free(group_members_list, free); } if (!include_group) { free(sid); free(domain_name); free(security_principle_str); return 0; } } /* Users and groups can inherit their privileges from their parents */ struct oscap_list *every_rights_sources = oscap_list_new(); oscap_list_add(every_rights_sources, wcsdup(security_principle)); get_user_local_groups(security_principle, every_rights_sources); get_user_global_groups(security_principle, every_rights_sources); /* Iterate over the items */ bool privileges_enabled[OVAL_PRIVILEGES_COUNT] = { false }; struct oscap_iterator *it = oscap_iterator_new(every_rights_sources); while (oscap_iterator_has_more(it)) { WCHAR *account_name = oscap_iterator_next(it); DWORD account_sid_len = 0; DWORD account_domain_name_len = 0; SID_NAME_USE account_sid_type; LookupAccountNameW(NULL, account_name, NULL, &account_sid_len, NULL, &account_domain_name_len, &account_sid_type); SID *account_sid = malloc(account_sid_len); WCHAR *account_domain_name = malloc(account_domain_name_len * sizeof(WCHAR)); if (!LookupAccountNameW(NULL, account_name, account_sid, &account_sid_len, account_domain_name, &account_domain_name_len, &account_sid_type)) { free(account_sid); free(account_domain_name); DWORD err = GetLastError(); char *error_message = oscap_windows_error_message(err); dD("LookupAccountNameW failed for '%s': %s", security_principle_str, error_message); free(error_message); free(security_principle_str); return 1; } LSA_UNICODE_STRING *granted_rights = NULL; ULONG granted_rights_count = 0; status = LsaEnumerateAccountRights(lsa_policy_handle, account_sid, &granted_rights, &granted_rights_count); if (status != STATUS_SUCCESS) { free(account_sid); free(account_domain_name); DWORD err = LsaNtStatusToWinError(status); char *error_message = oscap_windows_error_message(err); dD("LsaEnumerateAccountRights failed for '%s': %s", security_principle_str, error_message); free(error_message); /* We should not exit here, because when LsaEnumerateAccountRights * failed it can mean that the entity simply doesn't have any specific * privileges, it only inhertis privileges form its parent group(s). */ continue; } for (int i = 0; i < OVAL_PRIVILEGES_COUNT; i++) { if (!privileges_enabled[i]) { for (ULONG j = 0; j < granted_rights_count; j++) { if (wcscmp(granted_rights[j].Buffer, privileges_texts[i]) == 0) { privileges_enabled[i] = true; break; } } } } LsaFreeMemory(granted_rights); free(account_sid); free(account_domain_name); } oscap_iterator_free(it); oscap_list_free(every_rights_sources, free); /* Collect the OVAL item */ SEXP_t *item = probe_item_create(OVAL_WINDOWS_ACCESS_TOKEN, NULL, "security_principle", OVAL_DATATYPE_STRING, strdup(security_principle_str), NULL); for (int i = 0; i < OVAL_PRIVILEGES_COUNT; i++) { char *privilege_name = oscap_windows_wstr_to_str(privileges_texts[i]); /* Convert the element name to lowercase */ for (char *p = privilege_name; *p; p++) { *p = tolower(*p); } SEXP_t *privilege_value = SEXP_number_newb(privileges_enabled[i]); probe_item_ent_add(item, privilege_name, NULL, privilege_value); free(privilege_name); SEXP_free(privilege_value); } probe_item_collect(ctx, item); free(security_principle_str); return 0; }