Something went wrong. Try again.
Reactos
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198/* * Unit tests for security functions * * Copyright (c) 2004 Mike McCormack * Copyright (c) 2011,2013,2014,2016 Dmitry Timoshkov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
#include <stdarg.h>#include <stdio.h>
#include "ntstatus.h"#define WIN32_NO_STATUS#include "windef.h"#include "winbase.h"#include "winerror.h"#include "winternl.h"#include "aclapi.h"#include "winnt.h"#include "sddl.h"#include "ntsecapi.h"#include "lmcons.h"
#include "wine/test.h"
/* FIXME: Inspect */#define GetCurrentProcessToken() ((HANDLE)~(ULONG_PTR)3)#define GetCurrentThreadToken() ((HANDLE)~(ULONG_PTR)4)#define GetCurrentThreadEffectiveToken() ((HANDLE)~(ULONG_PTR)5)
#ifndef PROCESS_QUERY_LIMITED_INFORMATION#define PROCESS_QUERY_LIMITED_INFORMATION 0x1000#endif
/* PROCESS_ALL_ACCESS in Vista+ PSDKs is incompatible with older Windows versions */#define PROCESS_ALL_ACCESS_NT4 (PROCESS_ALL_ACCESS & ~0xf000)#define PROCESS_ALL_ACCESS_VISTA (PROCESS_ALL_ACCESS | 0xf000)
#ifndef EVENT_QUERY_STATE#define EVENT_QUERY_STATE 0x0001#endif
#ifndef SEMAPHORE_QUERY_STATE#define SEMAPHORE_QUERY_STATE 0x0001#endif
#ifndef THREAD_SET_LIMITED_INFORMATION#define THREAD_SET_LIMITED_INFORMATION 0x0400#define THREAD_QUERY_LIMITED_INFORMATION 0x0800#endif
#define THREAD_ALL_ACCESS_NT4 (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3ff)#define THREAD_ALL_ACCESS_VISTA (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xffff)
#define expect_eq(expr, value, type, format) { type ret_ = expr; ok((value) == ret_, #expr " expected " format " got " format "\n", (value), (ret_)); }
static BOOL (WINAPI *pAddAccessAllowedAceEx)(PACL, DWORD, DWORD, DWORD, PSID);static BOOL (WINAPI *pAddAccessDeniedAceEx)(PACL, DWORD, DWORD, DWORD, PSID);static BOOL (WINAPI *pAddAuditAccessAceEx)(PACL, DWORD, DWORD, DWORD, PSID, BOOL, BOOL);static BOOL (WINAPI *pAddMandatoryAce)(PACL,DWORD,DWORD,DWORD,PSID);static VOID (WINAPI *pBuildTrusteeWithSidA)( PTRUSTEEA pTrustee, PSID pSid );static VOID (WINAPI *pBuildTrusteeWithNameA)( PTRUSTEEA pTrustee, LPSTR pName );static VOID (WINAPI *pBuildTrusteeWithObjectsAndNameA)( PTRUSTEEA pTrustee, POBJECTS_AND_NAME_A pObjName, SE_OBJECT_TYPE ObjectType, LPSTR ObjectTypeName, LPSTR InheritedObjectTypeName, LPSTR Name );static VOID (WINAPI *pBuildTrusteeWithObjectsAndSidA)( PTRUSTEEA pTrustee, POBJECTS_AND_SID pObjSid, GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid );static LPSTR (WINAPI *pGetTrusteeNameA)( PTRUSTEEA pTrustee );static BOOL (WINAPI *pMakeSelfRelativeSD)( PSECURITY_DESCRIPTOR, PSECURITY_DESCRIPTOR, LPDWORD );static BOOL (WINAPI *pConvertStringSidToSidA)( LPCSTR str, PSID pSid );static BOOL (WINAPI *pCheckTokenMembership)(HANDLE, PSID, PBOOL);static BOOL (WINAPI *pConvertStringSecurityDescriptorToSecurityDescriptorA)(LPCSTR, DWORD, PSECURITY_DESCRIPTOR*, PULONG );static BOOL (WINAPI *pConvertStringSecurityDescriptorToSecurityDescriptorW)(LPCWSTR, DWORD, PSECURITY_DESCRIPTOR*, PULONG );static BOOL (WINAPI *pConvertSecurityDescriptorToStringSecurityDescriptorA)(PSECURITY_DESCRIPTOR, DWORD, SECURITY_INFORMATION, LPSTR *, PULONG );static BOOL (WINAPI *pGetFileSecurityA)(LPCSTR, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR, DWORD, LPDWORD);static BOOL (WINAPI *pSetFileSecurityA)(LPCSTR, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR);static DWORD (WINAPI *pGetNamedSecurityInfoA)(LPSTR, SE_OBJECT_TYPE, SECURITY_INFORMATION, PSID*, PSID*, PACL*, PACL*, PSECURITY_DESCRIPTOR*);static DWORD (WINAPI *pSetNamedSecurityInfoA)(LPSTR, SE_OBJECT_TYPE, SECURITY_INFORMATION, PSID, PSID, PACL, PACL);static PDWORD (WINAPI *pGetSidSubAuthority)(PSID, DWORD);static PUCHAR (WINAPI *pGetSidSubAuthorityCount)(PSID);static BOOL (WINAPI *pIsValidSid)(PSID);static DWORD (WINAPI *pRtlAdjustPrivilege)(ULONG,BOOLEAN,BOOLEAN,PBOOLEAN);static BOOL (WINAPI *pCreateWellKnownSid)(WELL_KNOWN_SID_TYPE,PSID,PSID,DWORD*);static BOOL (WINAPI *pDuplicateTokenEx)(HANDLE,DWORD,LPSECURITY_ATTRIBUTES, SECURITY_IMPERSONATION_LEVEL,TOKEN_TYPE,PHANDLE);
static NTSTATUS (WINAPI *pLsaQueryInformationPolicy)(LSA_HANDLE,POLICY_INFORMATION_CLASS,PVOID*);static NTSTATUS (WINAPI *pLsaClose)(LSA_HANDLE);static NTSTATUS (WINAPI *pLsaFreeMemory)(PVOID);static NTSTATUS (WINAPI *pLsaOpenPolicy)(PLSA_UNICODE_STRING,PLSA_OBJECT_ATTRIBUTES,ACCESS_MASK,PLSA_HANDLE);static NTSTATUS (WINAPI *pNtQueryObject)(HANDLE,OBJECT_INFORMATION_CLASS,PVOID,ULONG,PULONG);static DWORD (WINAPI *pSetEntriesInAclW)(ULONG, PEXPLICIT_ACCESSW, PACL, PACL*);static DWORD (WINAPI *pSetEntriesInAclA)(ULONG, PEXPLICIT_ACCESSA, PACL, PACL*);static BOOL (WINAPI *pSetSecurityDescriptorControl)(PSECURITY_DESCRIPTOR, SECURITY_DESCRIPTOR_CONTROL, SECURITY_DESCRIPTOR_CONTROL);static DWORD (WINAPI *pGetSecurityInfo)(HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION, PSID*, PSID*, PACL*, PACL*, PSECURITY_DESCRIPTOR*);static DWORD (WINAPI *pSetSecurityInfo)(HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION, PSID, PSID, PACL, PACL);static NTSTATUS (WINAPI *pNtAccessCheck)(PSECURITY_DESCRIPTOR, HANDLE, ACCESS_MASK, PGENERIC_MAPPING, PPRIVILEGE_SET, PULONG, PULONG, NTSTATUS*);static BOOL (WINAPI *pCreateRestrictedToken)(HANDLE, DWORD, DWORD, PSID_AND_ATTRIBUTES, DWORD, PLUID_AND_ATTRIBUTES, DWORD, PSID_AND_ATTRIBUTES, PHANDLE);static BOOL (WINAPI *pGetAclInformation)(PACL,LPVOID,DWORD,ACL_INFORMATION_CLASS);static BOOL (WINAPI *pGetAce)(PACL,DWORD,LPVOID*);static NTSTATUS (WINAPI *pNtSetSecurityObject)(HANDLE,SECURITY_INFORMATION,PSECURITY_DESCRIPTOR);static NTSTATUS (WINAPI *pNtCreateFile)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_BLOCK,PLARGE_INTEGER,ULONG,ULONG,ULONG,ULONG,PVOID,ULONG);static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)(LPCWSTR,PUNICODE_STRING,PWSTR*,CURDIR*);static NTSTATUS (WINAPI *pRtlAnsiStringToUnicodeString)(PUNICODE_STRING,PCANSI_STRING,BOOLEAN);static BOOL (WINAPI *pGetWindowsAccountDomainSid)(PSID,PSID,DWORD*);static void (WINAPI *pRtlInitAnsiString)(PANSI_STRING,PCSZ);static NTSTATUS (WINAPI *pRtlFreeUnicodeString)(PUNICODE_STRING);static PSID_IDENTIFIER_AUTHORITY (WINAPI *pGetSidIdentifierAuthority)(PSID);static DWORD (WINAPI *pGetExplicitEntriesFromAclW)(PACL,PULONG,PEXPLICIT_ACCESSW*);
static HMODULE hmod;static int myARGC;static char** myARGV;
#define SID_SLOTS 4static char debugsid_str[SID_SLOTS][256];static int debugsid_index = 0;static const char* debugstr_sid(PSID sid){ LPSTR sidstr; DWORD le = GetLastError(); char* res = debugsid_str[debugsid_index]; debugsid_index = (debugsid_index + 1) % SID_SLOTS;
if (!ConvertSidToStringSidA(sid, &sidstr)) sprintf(res, "ConvertSidToStringSidA failed le=%u", GetLastError()); else if (strlen(sidstr) > sizeof(*debugsid_str) - 1) { memcpy(res, sidstr, sizeof(*debugsid_str) - 4); strcpy(res + sizeof(*debugsid_str) - 4, "..."); LocalFree(sidstr); } else { strcpy(res, sidstr); LocalFree(sidstr); } /* Restore the last error in case ConvertSidToStringSidA() modified it */ SetLastError(le); return res;}
static void init(void){ HMODULE hntdll;
hntdll = GetModuleHandleA("ntdll.dll"); pNtQueryObject = (void *)GetProcAddress( hntdll, "NtQueryObject" ); pNtAccessCheck = (void *)GetProcAddress( hntdll, "NtAccessCheck" ); pNtSetSecurityObject = (void *)GetProcAddress(hntdll, "NtSetSecurityObject"); pNtCreateFile = (void *)GetProcAddress(hntdll, "NtCreateFile"); pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U"); pRtlAnsiStringToUnicodeString = (void *)GetProcAddress(hntdll, "RtlAnsiStringToUnicodeString"); pRtlInitAnsiString = (void *)GetProcAddress(hntdll, "RtlInitAnsiString"); pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
hmod = GetModuleHandleA("advapi32.dll"); pAddAccessAllowedAceEx = (void *)GetProcAddress(hmod, "AddAccessAllowedAceEx"); pAddAccessDeniedAceEx = (void *)GetProcAddress(hmod, "AddAccessDeniedAceEx"); pAddAuditAccessAceEx = (void *)GetProcAddress(hmod, "AddAuditAccessAceEx"); pAddMandatoryAce = (void *)GetProcAddress(hmod, "AddMandatoryAce"); pCheckTokenMembership = (void *)GetProcAddress(hmod, "CheckTokenMembership"); pConvertStringSecurityDescriptorToSecurityDescriptorA = (void *)GetProcAddress(hmod, "ConvertStringSecurityDescriptorToSecurityDescriptorA" ); pConvertStringSecurityDescriptorToSecurityDescriptorW = (void *)GetProcAddress(hmod, "ConvertStringSecurityDescriptorToSecurityDescriptorW" ); pConvertSecurityDescriptorToStringSecurityDescriptorA = (void *)GetProcAddress(hmod, "ConvertSecurityDescriptorToStringSecurityDescriptorA" ); pGetFileSecurityA = (void *)GetProcAddress(hmod, "GetFileSecurityA" ); pSetFileSecurityA = (void *)GetProcAddress(hmod, "SetFileSecurityA" ); pCreateWellKnownSid = (void *)GetProcAddress( hmod, "CreateWellKnownSid" ); pGetNamedSecurityInfoA = (void *)GetProcAddress(hmod, "GetNamedSecurityInfoA"); pSetNamedSecurityInfoA = (void *)GetProcAddress(hmod, "SetNamedSecurityInfoA"); pGetSidSubAuthority = (void *)GetProcAddress(hmod, "GetSidSubAuthority"); pGetSidSubAuthorityCount = (void *)GetProcAddress(hmod, "GetSidSubAuthorityCount"); pIsValidSid = (void *)GetProcAddress(hmod, "IsValidSid"); pMakeSelfRelativeSD = (void *)GetProcAddress(hmod, "MakeSelfRelativeSD"); pSetEntriesInAclW = (void *)GetProcAddress(hmod, "SetEntriesInAclW"); pSetEntriesInAclA = (void *)GetProcAddress(hmod, "SetEntriesInAclA"); pSetSecurityDescriptorControl = (void *)GetProcAddress(hmod, "SetSecurityDescriptorControl"); pGetSecurityInfo = (void *)GetProcAddress(hmod, "GetSecurityInfo"); pSetSecurityInfo = (void *)GetProcAddress(hmod, "SetSecurityInfo"); pCreateRestrictedToken = (void *)GetProcAddress(hmod, "CreateRestrictedToken"); pConvertStringSidToSidA = (void *)GetProcAddress(hmod, "ConvertStringSidToSidA"); pGetAclInformation = (void *)GetProcAddress(hmod, "GetAclInformation"); pGetAce = (void *)GetProcAddress(hmod, "GetAce"); pGetWindowsAccountDomainSid = (void *)GetProcAddress(hmod, "GetWindowsAccountDomainSid"); pGetSidIdentifierAuthority = (void *)GetProcAddress(hmod, "GetSidIdentifierAuthority"); pDuplicateTokenEx = (void *)GetProcAddress(hmod, "DuplicateTokenEx"); pGetExplicitEntriesFromAclW = (void *)GetProcAddress(hmod, "GetExplicitEntriesFromAclW");
myARGC = winetest_get_mainargs( &myARGV );}
static SECURITY_DESCRIPTOR* test_get_security_descriptor(HANDLE handle, int line){ /* use HeapFree(GetProcessHeap(), 0, sd); when done */ DWORD ret, length, needed; SECURITY_DESCRIPTOR *sd;
needed = 0xdeadbeef; SetLastError(0xdeadbeef); ret = GetKernelObjectSecurity(handle, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, NULL, 0, &needed); ok_(__FILE__, line)(!ret, "GetKernelObjectSecurity should fail\n"); ok_(__FILE__, line)(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); ok_(__FILE__, line)(needed != 0xdeadbeef, "GetKernelObjectSecurity should return required buffer length\n");
length = needed; sd = HeapAlloc(GetProcessHeap(), 0, length);
needed = 0xdeadbeef; SetLastError(0xdeadbeef); ret = GetKernelObjectSecurity(handle, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, sd, length, &needed); ok_(__FILE__, line)(ret, "GetKernelObjectSecurity error %d\n", GetLastError()); ok_(__FILE__, line)(needed == length || needed == 0 /* file, pipe */, "GetKernelObjectSecurity should return %u instead of %u\n", length, needed); return sd;}
static void test_owner_equal(HANDLE Handle, PSID expected, int line){ BOOL res; SECURITY_DESCRIPTOR *queriedSD = NULL; PSID owner; BOOL owner_defaulted;
queriedSD = test_get_security_descriptor( Handle, line );
res = GetSecurityDescriptorOwner(queriedSD, &owner, &owner_defaulted); ok_(__FILE__, line)(res, "GetSecurityDescriptorOwner failed with error %d\n", GetLastError());
ok_(__FILE__, line)(EqualSid(owner, expected), "Owner SIDs are not equal %s != %s\n", debugstr_sid(owner), debugstr_sid(expected)); ok_(__FILE__, line)(!owner_defaulted, "Defaulted is true\n");
HeapFree(GetProcessHeap(), 0, queriedSD);}
static void test_group_equal(HANDLE Handle, PSID expected, int line){ BOOL res; SECURITY_DESCRIPTOR *queriedSD = NULL; PSID group; BOOL group_defaulted;
queriedSD = test_get_security_descriptor( Handle, line );
res = GetSecurityDescriptorGroup(queriedSD, &group, &group_defaulted); ok_(__FILE__, line)(res, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError());
ok_(__FILE__, line)(EqualSid(group, expected), "Group SIDs are not equal %s != %s\n", debugstr_sid(group), debugstr_sid(expected)); ok_(__FILE__, line)(!group_defaulted, "Defaulted is true\n");
HeapFree(GetProcessHeap(), 0, queriedSD);}
static void test_sid(void){ static struct { SID_IDENTIFIER_AUTHORITY auth; const char *refStr; } refs[] = { { { {0x00,0x00,0x33,0x44,0x55,0x66} }, "S-1-860116326-1" }, { { {0x00,0x00,0x01,0x02,0x03,0x04} }, "S-1-16909060-1" }, { { {0x00,0x00,0x00,0x01,0x02,0x03} }, "S-1-66051-1" }, { { {0x00,0x00,0x00,0x00,0x01,0x02} }, "S-1-258-1" }, { { {0x00,0x00,0x00,0x00,0x00,0x02} }, "S-1-2-1" }, { { {0x00,0x00,0x00,0x00,0x00,0x0c} }, "S-1-12-1" }, }; static const struct { const char *str; WELL_KNOWN_SID_TYPE sid_type; BOOL optional; } strsid_table[] = { /* Please keep the list sorted. */ { "AC", WinBuiltinAnyPackageSid, TRUE }, { "AN", WinAnonymousSid }, { "AO", WinBuiltinAccountOperatorsSid }, { "AU", WinAuthenticatedUserSid }, { "BA", WinBuiltinAdministratorsSid }, { "BG", WinBuiltinGuestsSid }, { "BO", WinBuiltinBackupOperatorsSid }, { "BU", WinBuiltinUsersSid }, { "CA", WinAccountCertAdminsSid, TRUE}, { "CG", WinCreatorGroupSid }, { "CO", WinCreatorOwnerSid }, { "DA", WinAccountDomainAdminsSid, TRUE}, { "DC", WinAccountComputersSid, TRUE}, { "DD", WinAccountControllersSid, TRUE}, { "DG", WinAccountDomainGuestsSid, TRUE}, { "DU", WinAccountDomainUsersSid, TRUE}, { "EA", WinAccountEnterpriseAdminsSid, TRUE}, { "ED", WinEnterpriseControllersSid }, { "IU", WinInteractiveSid }, { "LA", WinAccountAdministratorSid }, { "LG", WinAccountGuestSid }, { "LS", WinLocalServiceSid }, { "NO", WinBuiltinNetworkConfigurationOperatorsSid }, { "NS", WinNetworkServiceSid }, { "NU", WinNetworkSid }, { "PA", WinAccountPolicyAdminsSid, TRUE}, { "PO", WinBuiltinPrintOperatorsSid }, { "PS", WinSelfSid }, { "PU", WinBuiltinPowerUsersSid }, { "RC", WinRestrictedCodeSid }, { "RD", WinBuiltinRemoteDesktopUsersSid }, { "RE", WinBuiltinReplicatorSid }, { "RS", WinAccountRasAndIasServersSid, TRUE }, { "RU", WinBuiltinPreWindows2000CompatibleAccessSid }, { "SA", WinAccountSchemaAdminsSid, TRUE }, { "SO", WinBuiltinSystemOperatorsSid }, { "SU", WinServiceSid }, { "SY", WinLocalSystemSid }, { "WD", WinWorldSid }, }; SID_IDENTIFIER_AUTHORITY domain_ident = { SECURITY_NT_AUTHORITY }; const char noSubAuthStr[] = "S-1-5"; unsigned int i; PSID psid, domain_sid; SID *pisid; BOOL r; LPSTR str;
if( !pConvertStringSidToSidA ) { win_skip("ConvertSidToStringSidA or ConvertStringSidToSidA not available\n"); return; }
r = pConvertStringSidToSidA( NULL, NULL ); ok( !r, "expected failure with NULL parameters\n" ); if( GetLastError() == ERROR_CALL_NOT_IMPLEMENTED ) return; ok( GetLastError() == ERROR_INVALID_PARAMETER, "expected GetLastError() is ERROR_INVALID_PARAMETER, got %d\n", GetLastError() );
r = pConvertStringSidToSidA( refs[0].refStr, NULL ); ok( !r && GetLastError() == ERROR_INVALID_PARAMETER, "expected GetLastError() is ERROR_INVALID_PARAMETER, got %d\n", GetLastError() );
r = pConvertStringSidToSidA( NULL, &str ); ok( !r && GetLastError() == ERROR_INVALID_PARAMETER, "expected GetLastError() is ERROR_INVALID_PARAMETER, got %d\n", GetLastError() );
r = pConvertStringSidToSidA( noSubAuthStr, &psid ); ok( !r, "expected failure with no sub authorities\n" ); ok( GetLastError() == ERROR_INVALID_SID, "expected GetLastError() is ERROR_INVALID_SID, got %d\n", GetLastError() );
ok(pConvertStringSidToSidA("S-1-5-21-93476-23408-4576", &psid), "ConvertStringSidToSidA failed\n"); pisid = psid; ok(pisid->SubAuthorityCount == 4, "Invalid sub authority count - expected 4, got %d\n", pisid->SubAuthorityCount); ok(pisid->SubAuthority[0] == 21, "Invalid subauthority 0 - expected 21, got %d\n", pisid->SubAuthority[0]); ok(pisid->SubAuthority[3] == 4576, "Invalid subauthority 0 - expected 4576, got %d\n", pisid->SubAuthority[3]); LocalFree(str); LocalFree(psid);
for( i = 0; i < sizeof(refs) / sizeof(refs[0]); i++ ) { r = AllocateAndInitializeSid( &refs[i].auth, 1,1,0,0,0,0,0,0,0, &psid ); ok( r, "failed to allocate sid\n" ); r = ConvertSidToStringSidA( psid, &str ); ok( r, "failed to convert sid\n" ); if (r) { ok( !strcmp( str, refs[i].refStr ), "incorrect sid, expected %s, got %s\n", refs[i].refStr, str ); LocalFree( str ); } if( psid ) FreeSid( psid );
r = pConvertStringSidToSidA( refs[i].refStr, &psid ); ok( r, "failed to parse sid string\n" ); pisid = psid; ok( pisid && !memcmp( pisid->IdentifierAuthority.Value, refs[i].auth.Value, sizeof(refs[i].auth) ), "string sid %s didn't parse to expected value\n" "(got 0x%04x%08x, expected 0x%04x%08x)\n", refs[i].refStr, MAKEWORD( pisid->IdentifierAuthority.Value[1], pisid->IdentifierAuthority.Value[0] ), MAKELONG( MAKEWORD( pisid->IdentifierAuthority.Value[5], pisid->IdentifierAuthority.Value[4] ), MAKEWORD( pisid->IdentifierAuthority.Value[3], pisid->IdentifierAuthority.Value[2] ) ), MAKEWORD( refs[i].auth.Value[1], refs[i].auth.Value[0] ), MAKELONG( MAKEWORD( refs[i].auth.Value[5], refs[i].auth.Value[4] ), MAKEWORD( refs[i].auth.Value[3], refs[i].auth.Value[2] ) ) ); if( psid ) LocalFree( psid ); }
/* string constant format not supported before XP */ r = pConvertStringSidToSidA("AN", &psid); if(!r) { win_skip("String constant format not supported\n"); return; } LocalFree(psid);
AllocateAndInitializeSid(&domain_ident, 4, SECURITY_NT_NON_UNIQUE, 0, 0, 0, 0, 0, 0, 0, &domain_sid);
for(i = 0; i < sizeof(strsid_table) / sizeof(strsid_table[0]); i++) { SetLastError(0xdeadbeef); r = pConvertStringSidToSidA(strsid_table[i].str, &psid);
if (!(strsid_table[i].optional)) { ok(r, "%s: got %u\n", strsid_table[i].str, GetLastError()); }
if (r) { char buf[SECURITY_MAX_SID_SIZE]; char *sid_string, *well_known_sid_string; DWORD n, size;
/* zero out domain id before comparison to simplify things */ if (strsid_table[i].sid_type == WinAccountAdministratorSid || strsid_table[i].sid_type == WinAccountGuestSid) { for (n = 1; n <= 3; n++) *GetSidSubAuthority(psid, n) = 0; }
r = ConvertSidToStringSidA(psid, &sid_string); ok(r, "%s: ConvertSidToStringSid error %u\n", strsid_table[i].str, GetLastError()); if (winetest_debug > 1) trace("%s => %s\n", strsid_table[i].str, sid_string);
size = sizeof(buf); r = pCreateWellKnownSid(strsid_table[i].sid_type, domain_sid, buf, &size); ok(r, "%u: CreateWellKnownSid(%u) error %u\n", i, strsid_table[i].sid_type, GetLastError());
r = ConvertSidToStringSidA(buf, &well_known_sid_string); ok(r, "%u: ConvertSidToStringSi(%u) error %u\n", i, strsid_table[i].sid_type, GetLastError()); if (winetest_debug > 1) trace("%u => %s\n", strsid_table[i].sid_type, well_known_sid_string);
ok(strcmp(sid_string, well_known_sid_string) == 0, "%u: (%u) expected %s, got %s\n", i, strsid_table[i].sid_type, well_known_sid_string, sid_string);
LocalFree(well_known_sid_string); LocalFree(sid_string); LocalFree(psid); } else { if (GetLastError() != ERROR_INVALID_SID) trace(" %s: couldn't be converted, returned %d\n", strsid_table[i].str, GetLastError()); else trace(" %s: couldn't be converted\n", strsid_table[i].str); } }
LocalFree(domain_sid);}
static void test_trustee(void){ GUID ObjectType = {0x12345678, 0x1234, 0x5678, {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}}; GUID InheritedObjectType = {0x23456789, 0x2345, 0x6786, {0x2, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99}}; GUID ZeroGuid; OBJECTS_AND_NAME_A oan; OBJECTS_AND_SID oas; TRUSTEEA trustee; PSID psid; char szObjectTypeName[] = "ObjectTypeName"; char szInheritedObjectTypeName[] = "InheritedObjectTypeName"; char szTrusteeName[] = "szTrusteeName"; SID_IDENTIFIER_AUTHORITY auth = { {0x11,0x22,0,0,0, 0} };
memset( &ZeroGuid, 0x00, sizeof (ZeroGuid) );
pBuildTrusteeWithSidA = (void *)GetProcAddress( hmod, "BuildTrusteeWithSidA" ); pBuildTrusteeWithNameA = (void *)GetProcAddress( hmod, "BuildTrusteeWithNameA" ); pBuildTrusteeWithObjectsAndNameA = (void *)GetProcAddress (hmod, "BuildTrusteeWithObjectsAndNameA" ); pBuildTrusteeWithObjectsAndSidA = (void *)GetProcAddress (hmod, "BuildTrusteeWithObjectsAndSidA" ); pGetTrusteeNameA = (void *)GetProcAddress (hmod, "GetTrusteeNameA" ); if( !pBuildTrusteeWithSidA || !pBuildTrusteeWithNameA || !pBuildTrusteeWithObjectsAndNameA || !pBuildTrusteeWithObjectsAndSidA || !pGetTrusteeNameA ) return;
if ( ! AllocateAndInitializeSid( &auth, 1, 42, 0,0,0,0,0,0,0,&psid ) ) { trace( "failed to init SID\n" ); return; }
/* test BuildTrusteeWithSidA */ memset( &trustee, 0xff, sizeof trustee ); pBuildTrusteeWithSidA( &trustee, psid );
ok( trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n"); ok( trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n"); ok( trustee.TrusteeForm == TRUSTEE_IS_SID, "TrusteeForm wrong\n"); ok( trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n"); ok( trustee.ptstrName == psid, "ptstrName wrong\n" );
/* test BuildTrusteeWithObjectsAndSidA (test 1) */ memset( &trustee, 0xff, sizeof trustee ); memset( &oas, 0xff, sizeof(oas) ); pBuildTrusteeWithObjectsAndSidA(&trustee, &oas, &ObjectType, &InheritedObjectType, psid);
ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n"); ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n"); ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_SID, "TrusteeForm wrong\n"); ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n"); ok(trustee.ptstrName == (LPSTR)&oas, "ptstrName wrong\n"); ok(oas.ObjectsPresent == (ACE_OBJECT_TYPE_PRESENT | ACE_INHERITED_OBJECT_TYPE_PRESENT), "ObjectsPresent wrong\n"); ok(!memcmp(&oas.ObjectTypeGuid, &ObjectType, sizeof(GUID)), "ObjectTypeGuid wrong\n"); ok(!memcmp(&oas.InheritedObjectTypeGuid, &InheritedObjectType, sizeof(GUID)), "InheritedObjectTypeGuid wrong\n"); ok(oas.pSid == psid, "pSid wrong\n");
/* test GetTrusteeNameA */ ok(pGetTrusteeNameA(&trustee) == (LPSTR)&oas, "GetTrusteeName returned wrong value\n");
/* test BuildTrusteeWithObjectsAndSidA (test 2) */ memset( &trustee, 0xff, sizeof trustee ); memset( &oas, 0xff, sizeof(oas) ); pBuildTrusteeWithObjectsAndSidA(&trustee, &oas, NULL, &InheritedObjectType, psid);
ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n"); ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n"); ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_SID, "TrusteeForm wrong\n"); ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n"); ok(trustee.ptstrName == (LPSTR)&oas, "ptstrName wrong\n"); ok(oas.ObjectsPresent == ACE_INHERITED_OBJECT_TYPE_PRESENT, "ObjectsPresent wrong\n"); ok(!memcmp(&oas.ObjectTypeGuid, &ZeroGuid, sizeof(GUID)), "ObjectTypeGuid wrong\n"); ok(!memcmp(&oas.InheritedObjectTypeGuid, &InheritedObjectType, sizeof(GUID)), "InheritedObjectTypeGuid wrong\n"); ok(oas.pSid == psid, "pSid wrong\n");
FreeSid( psid );
/* test BuildTrusteeWithNameA */ memset( &trustee, 0xff, sizeof trustee ); pBuildTrusteeWithNameA( &trustee, szTrusteeName );
ok( trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n"); ok( trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n"); ok( trustee.TrusteeForm == TRUSTEE_IS_NAME, "TrusteeForm wrong\n"); ok( trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n"); ok( trustee.ptstrName == szTrusteeName, "ptstrName wrong\n" );
/* test BuildTrusteeWithObjectsAndNameA (test 1) */ memset( &trustee, 0xff, sizeof trustee ); memset( &oan, 0xff, sizeof(oan) ); pBuildTrusteeWithObjectsAndNameA(&trustee, &oan, SE_KERNEL_OBJECT, szObjectTypeName, szInheritedObjectTypeName, szTrusteeName);
ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n"); ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n"); ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_NAME, "TrusteeForm wrong\n"); ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n"); ok(trustee.ptstrName == (LPSTR)&oan, "ptstrName wrong\n"); ok(oan.ObjectsPresent == (ACE_OBJECT_TYPE_PRESENT | ACE_INHERITED_OBJECT_TYPE_PRESENT), "ObjectsPresent wrong\n"); ok(oan.ObjectType == SE_KERNEL_OBJECT, "ObjectType wrong\n"); ok(oan.InheritedObjectTypeName == szInheritedObjectTypeName, "InheritedObjectTypeName wrong\n"); ok(oan.ptstrName == szTrusteeName, "szTrusteeName wrong\n");
/* test GetTrusteeNameA */ ok(pGetTrusteeNameA(&trustee) == (LPSTR)&oan, "GetTrusteeName returned wrong value\n");
/* test BuildTrusteeWithObjectsAndNameA (test 2) */ memset( &trustee, 0xff, sizeof trustee ); memset( &oan, 0xff, sizeof(oan) ); pBuildTrusteeWithObjectsAndNameA(&trustee, &oan, SE_KERNEL_OBJECT, NULL, szInheritedObjectTypeName, szTrusteeName);
ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n"); ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n"); ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_NAME, "TrusteeForm wrong\n"); ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n"); ok(trustee.ptstrName == (LPSTR)&oan, "ptstrName wrong\n"); ok(oan.ObjectsPresent == ACE_INHERITED_OBJECT_TYPE_PRESENT, "ObjectsPresent wrong\n"); ok(oan.ObjectType == SE_KERNEL_OBJECT, "ObjectType wrong\n"); ok(oan.InheritedObjectTypeName == szInheritedObjectTypeName, "InheritedObjectTypeName wrong\n"); ok(oan.ptstrName == szTrusteeName, "szTrusteeName wrong\n");
/* test BuildTrusteeWithObjectsAndNameA (test 3) */ memset( &trustee, 0xff, sizeof trustee ); memset( &oan, 0xff, sizeof(oan) ); pBuildTrusteeWithObjectsAndNameA(&trustee, &oan, SE_KERNEL_OBJECT, szObjectTypeName, NULL, szTrusteeName);
ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n"); ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n"); ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_NAME, "TrusteeForm wrong\n"); ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n"); ok(trustee.ptstrName == (LPSTR)&oan, "ptstrName wrong\n"); ok(oan.ObjectsPresent == ACE_OBJECT_TYPE_PRESENT, "ObjectsPresent wrong\n"); ok(oan.ObjectType == SE_KERNEL_OBJECT, "ObjectType wrong\n"); ok(oan.InheritedObjectTypeName == NULL, "InheritedObjectTypeName wrong\n"); ok(oan.ptstrName == szTrusteeName, "szTrusteeName wrong\n");} /* If the first isn't defined, assume none is */#ifndef SE_MIN_WELL_KNOWN_PRIVILEGE#define SE_MIN_WELL_KNOWN_PRIVILEGE 2L#define SE_CREATE_TOKEN_PRIVILEGE 2L#define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE 3L#define SE_LOCK_MEMORY_PRIVILEGE 4L#define SE_INCREASE_QUOTA_PRIVILEGE 5L#define SE_MACHINE_ACCOUNT_PRIVILEGE 6L#define SE_TCB_PRIVILEGE 7L#define SE_SECURITY_PRIVILEGE 8L#define SE_TAKE_OWNERSHIP_PRIVILEGE 9L#define SE_LOAD_DRIVER_PRIVILEGE 10L#define SE_SYSTEM_PROFILE_PRIVILEGE 11L#define SE_SYSTEMTIME_PRIVILEGE 12L#define SE_PROF_SINGLE_PROCESS_PRIVILEGE 13L#define SE_INC_BASE_PRIORITY_PRIVILEGE 14L#define SE_CREATE_PAGEFILE_PRIVILEGE 15L#define SE_CREATE_PERMANENT_PRIVILEGE 16L#define SE_BACKUP_PRIVILEGE 17L#define SE_RESTORE_PRIVILEGE 18L#define SE_SHUTDOWN_PRIVILEGE 19L#define SE_DEBUG_PRIVILEGE 20L#define SE_AUDIT_PRIVILEGE 21L#define SE_SYSTEM_ENVIRONMENT_PRIVILEGE 22L#define SE_CHANGE_NOTIFY_PRIVILEGE 23L#define SE_REMOTE_SHUTDOWN_PRIVILEGE 24L#define SE_UNDOCK_PRIVILEGE 25L#define SE_SYNC_AGENT_PRIVILEGE 26L#define SE_ENABLE_DELEGATION_PRIVILEGE 27L#define SE_MANAGE_VOLUME_PRIVILEGE 28L#define SE_IMPERSONATE_PRIVILEGE 29L#define SE_CREATE_GLOBAL_PRIVILEGE 30L#define SE_MAX_WELL_KNOWN_PRIVILEGE SE_CREATE_GLOBAL_PRIVILEGE#endif /* ndef SE_MIN_WELL_KNOWN_PRIVILEGE */
static void test_allocateLuid(void){ BOOL (WINAPI *pAllocateLocallyUniqueId)(PLUID); LUID luid1, luid2; BOOL ret;
pAllocateLocallyUniqueId = (void*)GetProcAddress(hmod, "AllocateLocallyUniqueId"); if (!pAllocateLocallyUniqueId) return;
ret = pAllocateLocallyUniqueId(&luid1); if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) return;
ok(ret, "AllocateLocallyUniqueId failed: %d\n", GetLastError()); ret = pAllocateLocallyUniqueId(&luid2); ok( ret, "AllocateLocallyUniqueId failed: %d\n", GetLastError()); ok(luid1.LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE || luid1.HighPart != 0, "AllocateLocallyUniqueId returned a well-known LUID\n"); ok(luid1.LowPart != luid2.LowPart || luid1.HighPart != luid2.HighPart, "AllocateLocallyUniqueId returned non-unique LUIDs\n"); ret = pAllocateLocallyUniqueId(NULL); ok( !ret && GetLastError() == ERROR_NOACCESS, "AllocateLocallyUniqueId(NULL) didn't return ERROR_NOACCESS: %d\n", GetLastError());}
static void test_lookupPrivilegeName(void){ BOOL (WINAPI *pLookupPrivilegeNameA)(LPCSTR, PLUID, LPSTR, LPDWORD); char buf[MAX_PATH]; /* arbitrary, seems long enough */ DWORD cchName = sizeof(buf); LUID luid = { 0, 0 }; LONG i; BOOL ret;
/* check whether it's available first */ pLookupPrivilegeNameA = (void*)GetProcAddress(hmod, "LookupPrivilegeNameA"); if (!pLookupPrivilegeNameA) return; luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE; ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName); if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) return;
/* check with a short buffer */ cchName = 0; luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE; ret = pLookupPrivilegeNameA(NULL, &luid, NULL, &cchName); ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "LookupPrivilegeNameA didn't fail with ERROR_INSUFFICIENT_BUFFER: %d\n", GetLastError()); ok(cchName == strlen("SeCreateTokenPrivilege") + 1, "LookupPrivilegeNameA returned an incorrect required length for\n" "SeCreateTokenPrivilege (got %d, expected %d)\n", cchName, lstrlenA("SeCreateTokenPrivilege") + 1); /* check a known value and its returned length on success */ cchName = sizeof(buf); ok(pLookupPrivilegeNameA(NULL, &luid, buf, &cchName) && cchName == strlen("SeCreateTokenPrivilege"), "LookupPrivilegeNameA returned an incorrect output length for\n" "SeCreateTokenPrivilege (got %d, expected %d)\n", cchName, (int)strlen("SeCreateTokenPrivilege")); /* check known values */ for (i = SE_MIN_WELL_KNOWN_PRIVILEGE; i <= SE_MAX_WELL_KNOWN_PRIVILEGE; i++) { luid.LowPart = i; cchName = sizeof(buf); ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName); ok( ret || GetLastError() == ERROR_NO_SUCH_PRIVILEGE, "LookupPrivilegeNameA(0.%d) failed: %d\n", i, GetLastError()); } /* check a bogus LUID */ luid.LowPart = 0xdeadbeef; cchName = sizeof(buf); ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName); ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE, "LookupPrivilegeNameA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %d\n", GetLastError()); /* check on a bogus system */ luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE; cchName = sizeof(buf); ret = pLookupPrivilegeNameA("b0gu5.Nam3", &luid, buf, &cchName); ok( !ret && (GetLastError() == RPC_S_SERVER_UNAVAILABLE || GetLastError() == RPC_S_INVALID_NET_ADDR) /* w2k8 */, "LookupPrivilegeNameA didn't fail with RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR: %d\n", GetLastError());}
struct NameToLUID{ const char *name; DWORD lowPart;};
static void test_lookupPrivilegeValue(void){ static const struct NameToLUID privs[] = { { "SeCreateTokenPrivilege", SE_CREATE_TOKEN_PRIVILEGE }, { "SeAssignPrimaryTokenPrivilege", SE_ASSIGNPRIMARYTOKEN_PRIVILEGE }, { "SeLockMemoryPrivilege", SE_LOCK_MEMORY_PRIVILEGE }, { "SeIncreaseQuotaPrivilege", SE_INCREASE_QUOTA_PRIVILEGE }, { "SeMachineAccountPrivilege", SE_MACHINE_ACCOUNT_PRIVILEGE }, { "SeTcbPrivilege", SE_TCB_PRIVILEGE }, { "SeSecurityPrivilege", SE_SECURITY_PRIVILEGE }, { "SeTakeOwnershipPrivilege", SE_TAKE_OWNERSHIP_PRIVILEGE }, { "SeLoadDriverPrivilege", SE_LOAD_DRIVER_PRIVILEGE }, { "SeSystemProfilePrivilege", SE_SYSTEM_PROFILE_PRIVILEGE }, { "SeSystemtimePrivilege", SE_SYSTEMTIME_PRIVILEGE }, { "SeProfileSingleProcessPrivilege", SE_PROF_SINGLE_PROCESS_PRIVILEGE }, { "SeIncreaseBasePriorityPrivilege", SE_INC_BASE_PRIORITY_PRIVILEGE }, { "SeCreatePagefilePrivilege", SE_CREATE_PAGEFILE_PRIVILEGE }, { "SeCreatePermanentPrivilege", SE_CREATE_PERMANENT_PRIVILEGE }, { "SeBackupPrivilege", SE_BACKUP_PRIVILEGE }, { "SeRestorePrivilege", SE_RESTORE_PRIVILEGE }, { "SeShutdownPrivilege", SE_SHUTDOWN_PRIVILEGE }, { "SeDebugPrivilege", SE_DEBUG_PRIVILEGE }, { "SeAuditPrivilege", SE_AUDIT_PRIVILEGE }, { "SeSystemEnvironmentPrivilege", SE_SYSTEM_ENVIRONMENT_PRIVILEGE }, { "SeChangeNotifyPrivilege", SE_CHANGE_NOTIFY_PRIVILEGE }, { "SeRemoteShutdownPrivilege", SE_REMOTE_SHUTDOWN_PRIVILEGE }, { "SeUndockPrivilege", SE_UNDOCK_PRIVILEGE }, { "SeSyncAgentPrivilege", SE_SYNC_AGENT_PRIVILEGE }, { "SeEnableDelegationPrivilege", SE_ENABLE_DELEGATION_PRIVILEGE }, { "SeManageVolumePrivilege", SE_MANAGE_VOLUME_PRIVILEGE }, { "SeImpersonatePrivilege", SE_IMPERSONATE_PRIVILEGE }, { "SeCreateGlobalPrivilege", SE_CREATE_GLOBAL_PRIVILEGE }, }; BOOL (WINAPI *pLookupPrivilegeValueA)(LPCSTR, LPCSTR, PLUID); unsigned int i; LUID luid; BOOL ret;
/* check whether it's available first */ pLookupPrivilegeValueA = (void*)GetProcAddress(hmod, "LookupPrivilegeValueA"); if (!pLookupPrivilegeValueA) return; ret = pLookupPrivilegeValueA(NULL, "SeCreateTokenPrivilege", &luid); if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) return;
/* check a bogus system name */ ret = pLookupPrivilegeValueA("b0gu5.Nam3", "SeCreateTokenPrivilege", &luid); ok( !ret && (GetLastError() == RPC_S_SERVER_UNAVAILABLE || GetLastError() == RPC_S_INVALID_NET_ADDR) /* w2k8 */, "LookupPrivilegeValueA didn't fail with RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR: %d\n", GetLastError()); /* check a NULL string */ ret = pLookupPrivilegeValueA(NULL, 0, &luid); ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE, "LookupPrivilegeValueA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %d\n", GetLastError()); /* check a bogus privilege name */ ret = pLookupPrivilegeValueA(NULL, "SeBogusPrivilege", &luid); ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE, "LookupPrivilegeValueA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %d\n", GetLastError()); /* check case insensitive */ ret = pLookupPrivilegeValueA(NULL, "sEcREATEtOKENpRIVILEGE", &luid); ok( ret, "LookupPrivilegeValueA(NULL, sEcREATEtOKENpRIVILEGE, &luid) failed: %d\n", GetLastError()); for (i = 0; i < sizeof(privs) / sizeof(privs[0]); i++) { /* Not all privileges are implemented on all Windows versions, so * don't worry if the call fails */ if (pLookupPrivilegeValueA(NULL, privs[i].name, &luid)) { ok(luid.LowPart == privs[i].lowPart, "LookupPrivilegeValueA returned an invalid LUID for %s\n", privs[i].name); } }}
static void test_luid(void){ test_allocateLuid(); test_lookupPrivilegeName(); test_lookupPrivilegeValue();}
static void test_FileSecurity(void){ char wintmpdir [MAX_PATH]; char path [MAX_PATH]; char file [MAX_PATH]; HANDLE fh, token; DWORD sdSize, retSize, rc, granted, priv_set_len; PRIVILEGE_SET priv_set; BOOL status; BYTE *sd; GENERIC_MAPPING mapping = { FILE_READ_DATA, FILE_WRITE_DATA, FILE_EXECUTE, FILE_ALL_ACCESS }; const SECURITY_INFORMATION request = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;
if (!pGetFileSecurityA) { win_skip ("GetFileSecurity is not available\n"); return; }
if (!pSetFileSecurityA) { win_skip ("SetFileSecurity is not available\n"); return; }
if (!GetTempPathA (sizeof (wintmpdir), wintmpdir)) { win_skip ("GetTempPathA failed\n"); return; }
/* Create a temporary directory and in it a temporary file */ strcat (strcpy (path, wintmpdir), "rary"); SetLastError(0xdeadbeef); rc = CreateDirectoryA (path, NULL); ok (rc || GetLastError() == ERROR_ALREADY_EXISTS, "CreateDirectoryA " "failed for '%s' with %d\n", path, GetLastError());
strcat (strcpy (file, path), "\\ess"); SetLastError(0xdeadbeef); fh = CreateFileA (file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); ok (fh != INVALID_HANDLE_VALUE, "CreateFileA " "failed for '%s' with %d\n", file, GetLastError()); CloseHandle (fh);
/* For the temporary file ... */
/* Get size needed */ retSize = 0; SetLastError(0xdeadbeef); rc = pGetFileSecurityA (file, request, NULL, 0, &retSize); if (!rc && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) { win_skip("GetFileSecurityA is not implemented\n"); goto cleanup; } ok (!rc, "GetFileSecurityA " "was expected to fail for '%s'\n", file); ok (GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetFileSecurityA " "returned %d; expected ERROR_INSUFFICIENT_BUFFER\n", GetLastError()); ok (retSize > sizeof (SECURITY_DESCRIPTOR), "GetFileSecurityA returned size %d\n", retSize);
sdSize = retSize; sd = HeapAlloc (GetProcessHeap (), 0, sdSize);
/* Get security descriptor for real */ retSize = -1; SetLastError(0xdeadbeef); rc = pGetFileSecurityA (file, request, sd, sdSize, &retSize); ok (rc, "GetFileSecurityA " "was not expected to fail '%s': %d\n", file, GetLastError()); ok (retSize == sdSize || broken(retSize == 0), /* NT4 */ "GetFileSecurityA returned size %d; expected %d\n", retSize, sdSize);
/* Use it to set security descriptor */ SetLastError(0xdeadbeef); rc = pSetFileSecurityA (file, request, sd); ok (rc, "SetFileSecurityA " "was not expected to fail '%s': %d\n", file, GetLastError());
HeapFree (GetProcessHeap (), 0, sd);
/* Repeat for the temporary directory ... */
/* Get size needed */ retSize = 0; SetLastError(0xdeadbeef); rc = pGetFileSecurityA (path, request, NULL, 0, &retSize); ok (!rc, "GetFileSecurityA " "was expected to fail for '%s'\n", path); ok (GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetFileSecurityA " "returned %d; expected ERROR_INSUFFICIENT_BUFFER\n", GetLastError()); ok (retSize > sizeof (SECURITY_DESCRIPTOR), "GetFileSecurityA returned size %d\n", retSize);
sdSize = retSize; sd = HeapAlloc (GetProcessHeap (), 0, sdSize);
/* Get security descriptor for real */ retSize = -1; SetLastError(0xdeadbeef); rc = pGetFileSecurityA (path, request, sd, sdSize, &retSize); ok (rc, "GetFileSecurityA " "was not expected to fail '%s': %d\n", path, GetLastError()); ok (retSize == sdSize || broken(retSize == 0), /* NT4 */ "GetFileSecurityA returned size %d; expected %d\n", retSize, sdSize);
/* Use it to set security descriptor */ SetLastError(0xdeadbeef); rc = pSetFileSecurityA (path, request, sd); ok (rc, "SetFileSecurityA " "was not expected to fail '%s': %d\n", path, GetLastError()); HeapFree (GetProcessHeap (), 0, sd);
/* Old test */ strcpy (wintmpdir, "\\Should not exist"); SetLastError(0xdeadbeef); rc = pGetFileSecurityA (wintmpdir, OWNER_SECURITY_INFORMATION, NULL, 0, &sdSize); ok (!rc, "GetFileSecurityA should fail for not existing directories/files\n"); ok (GetLastError() == ERROR_FILE_NOT_FOUND, "last error ERROR_FILE_NOT_FOUND expected, got %d\n", GetLastError());
cleanup: /* Remove temporary file and directory */ DeleteFileA(file); RemoveDirectoryA(path);
/* Test file access permissions for a file with FILE_ATTRIBUTE_ARCHIVE */ SetLastError(0xdeadbeef); rc = GetTempPathA(sizeof(wintmpdir), wintmpdir); ok(rc, "GetTempPath error %d\n", GetLastError());
SetLastError(0xdeadbeef); rc = GetTempFileNameA(wintmpdir, "tmp", 0, file); ok(rc, "GetTempFileName error %d\n", GetLastError());
rc = GetFileAttributesA(file); rc &= ~(FILE_ATTRIBUTE_NOT_CONTENT_INDEXED|FILE_ATTRIBUTE_COMPRESSED); ok(rc == FILE_ATTRIBUTE_ARCHIVE, "expected FILE_ATTRIBUTE_ARCHIVE got %#x\n", rc);
rc = GetFileSecurityA(file, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, NULL, 0, &sdSize); ok(!rc, "GetFileSecurity should fail\n"); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER got %d\n", GetLastError()); ok(sdSize > sizeof(SECURITY_DESCRIPTOR), "got sd size %d\n", sdSize);
sd = HeapAlloc(GetProcessHeap (), 0, sdSize); retSize = 0xdeadbeef; SetLastError(0xdeadbeef); rc = GetFileSecurityA(file, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, sd, sdSize, &retSize); ok(rc, "GetFileSecurity error %d\n", GetLastError()); ok(retSize == sdSize || broken(retSize == 0) /* NT4 */, "expected %d, got %d\n", sdSize, retSize);
SetLastError(0xdeadbeef); rc = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &token); ok(!rc, "OpenThreadToken should fail\n"); ok(GetLastError() == ERROR_NO_TOKEN, "expected ERROR_NO_TOKEN, got %d\n", GetLastError());
SetLastError(0xdeadbeef); rc = ImpersonateSelf(SecurityIdentification); ok(rc, "ImpersonateSelf error %d\n", GetLastError());
SetLastError(0xdeadbeef); rc = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &token); ok(rc, "OpenThreadToken error %d\n", GetLastError());
SetLastError(0xdeadbeef); rc = RevertToSelf(); ok(rc, "RevertToSelf error %d\n", GetLastError());
priv_set_len = sizeof(priv_set); granted = 0xdeadbeef; status = 0xdeadbeef; SetLastError(0xdeadbeef); rc = AccessCheck(sd, token, FILE_READ_DATA, &mapping, &priv_set, &priv_set_len, &granted, &status); ok(rc, "AccessCheck error %d\n", GetLastError()); ok(status == 1, "expected 1, got %d\n", status); ok(granted == FILE_READ_DATA, "expected FILE_READ_DATA, got %#x\n", granted);
granted = 0xdeadbeef; status = 0xdeadbeef; SetLastError(0xdeadbeef); rc = AccessCheck(sd, token, FILE_WRITE_DATA, &mapping, &priv_set, &priv_set_len, &granted, &status); ok(rc, "AccessCheck error %d\n", GetLastError()); ok(status == 1, "expected 1, got %d\n", status); ok(granted == FILE_WRITE_DATA, "expected FILE_WRITE_DATA, got %#x\n", granted);
granted = 0xdeadbeef; status = 0xdeadbeef; SetLastError(0xdeadbeef); rc = AccessCheck(sd, token, FILE_EXECUTE, &mapping, &priv_set, &priv_set_len, &granted, &status); ok(rc, "AccessCheck error %d\n", GetLastError()); ok(status == 1, "expected 1, got %d\n", status); ok(granted == FILE_EXECUTE, "expected FILE_EXECUTE, got %#x\n", granted);
granted = 0xdeadbeef; status = 0xdeadbeef; SetLastError(0xdeadbeef); rc = AccessCheck(sd, token, DELETE, &mapping, &priv_set, &priv_set_len, &granted, &status); ok(rc, "AccessCheck error %d\n", GetLastError()); ok(status == 1, "expected 1, got %d\n", status); ok(granted == DELETE, "expected DELETE, got %#x\n", granted);
granted = 0xdeadbeef; status = 0xdeadbeef; SetLastError(0xdeadbeef); rc = AccessCheck(sd, token, FILE_DELETE_CHILD, &mapping, &priv_set, &priv_set_len, &granted, &status); ok(rc, "AccessCheck error %d\n", GetLastError()); ok(status == 1, "expected 1, got %d\n", status); ok(granted == FILE_DELETE_CHILD, "expected FILE_DELETE_CHILD, got %#x\n", granted);
granted = 0xdeadbeef; status = 0xdeadbeef; SetLastError(0xdeadbeef); rc = AccessCheck(sd, token, 0x1ff, &mapping, &priv_set, &priv_set_len, &granted, &status); ok(rc, "AccessCheck error %d\n", GetLastError()); ok(status == 1, "expected 1, got %d\n", status); ok(granted == 0x1ff, "expected 0x1ff, got %#x\n", granted);
granted = 0xdeadbeef; status = 0xdeadbeef; SetLastError(0xdeadbeef); rc = AccessCheck(sd, token, FILE_ALL_ACCESS, &mapping, &priv_set, &priv_set_len, &granted, &status); ok(rc, "AccessCheck error %d\n", GetLastError()); ok(status == 1, "expected 1, got %d\n", status); ok(granted == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#x\n", granted);
SetLastError(0xdeadbeef); rc = AccessCheck(sd, token, 0xffffffff, &mapping, &priv_set, &priv_set_len, &granted, &status); ok(!rc, "AccessCheck should fail\n"); ok(GetLastError() == ERROR_GENERIC_NOT_MAPPED, "expected ERROR_GENERIC_NOT_MAPPED, got %d\n", GetLastError());
/* Test file access permissions for a file with FILE_ATTRIBUTE_READONLY */ SetLastError(0xdeadbeef); fh = CreateFileA(file, FILE_READ_DATA, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0); ok(fh != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError()); retSize = 0xdeadbeef; SetLastError(0xdeadbeef); rc = WriteFile(fh, "1", 1, &retSize, NULL); ok(!rc, "WriteFile should fail\n"); ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); ok(retSize == 0, "expected 0, got %d\n", retSize); CloseHandle(fh);
rc = GetFileAttributesA(file); rc &= ~(FILE_ATTRIBUTE_NOT_CONTENT_INDEXED|FILE_ATTRIBUTE_COMPRESSED);todo_wine ok(rc == (FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY), "expected FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY got %#x\n", rc);
SetLastError(0xdeadbeef); rc = SetFileAttributesA(file, FILE_ATTRIBUTE_ARCHIVE); ok(rc, "SetFileAttributes error %d\n", GetLastError()); SetLastError(0xdeadbeef); rc = DeleteFileA(file); ok(rc, "DeleteFile error %d\n", GetLastError());
SetLastError(0xdeadbeef); fh = CreateFileA(file, FILE_READ_DATA, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0); ok(fh != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError()); retSize = 0xdeadbeef; SetLastError(0xdeadbeef); rc = WriteFile(fh, "1", 1, &retSize, NULL); ok(!rc, "WriteFile should fail\n"); ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); ok(retSize == 0, "expected 0, got %d\n", retSize); CloseHandle(fh);
rc = GetFileAttributesA(file); rc &= ~(FILE_ATTRIBUTE_NOT_CONTENT_INDEXED|FILE_ATTRIBUTE_COMPRESSED); ok(rc == (FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY), "expected FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY got %#x\n", rc);
retSize = 0xdeadbeef; SetLastError(0xdeadbeef); rc = GetFileSecurityA(file, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, sd, sdSize, &retSize); ok(rc, "GetFileSecurity error %d\n", GetLastError()); ok(retSize == sdSize || broken(retSize == 0) /* NT4 */, "expected %d, got %d\n", sdSize, retSize);
priv_set_len = sizeof(priv_set); granted = 0xdeadbeef; status = 0xdeadbeef; SetLastError(0xdeadbeef); rc = AccessCheck(sd, token, FILE_READ_DATA, &mapping, &priv_set, &priv_set_len, &granted, &status); ok(rc, "AccessCheck error %d\n", GetLastError()); ok(status == 1, "expected 1, got %d\n", status); ok(granted == FILE_READ_DATA, "expected FILE_READ_DATA, got %#x\n", granted);
granted = 0xdeadbeef; status = 0xdeadbeef; SetLastError(0xdeadbeef); rc = AccessCheck(sd, token, FILE_WRITE_DATA, &mapping, &priv_set, &priv_set_len, &granted, &status); ok(rc, "AccessCheck error %d\n", GetLastError());todo_wine { ok(status == 1, "expected 1, got %d\n", status); ok(granted == FILE_WRITE_DATA, "expected FILE_WRITE_DATA, got %#x\n", granted);} granted = 0xdeadbeef; status = 0xdeadbeef; SetLastError(0xdeadbeef); rc = AccessCheck(sd, token, FILE_EXECUTE, &mapping, &priv_set, &priv_set_len, &granted, &status); ok(rc, "AccessCheck error %d\n", GetLastError()); ok(status == 1, "expected 1, got %d\n", status); ok(granted == FILE_EXECUTE, "expected FILE_EXECUTE, got %#x\n", granted);
granted = 0xdeadbeef; status = 0xdeadbeef; SetLastError(0xdeadbeef); rc = AccessCheck(sd, token, DELETE, &mapping, &priv_set, &priv_set_len, &granted, &status); ok(rc, "AccessCheck error %d\n", GetLastError());todo_wine { ok(status == 1, "expected 1, got %d\n", status); ok(granted == DELETE, "expected DELETE, got %#x\n", granted);} granted = 0xdeadbeef; status = 0xdeadbeef; SetLastError(0xdeadbeef); rc = AccessCheck(sd, token, FILE_DELETE_CHILD, &mapping, &priv_set, &priv_set_len, &granted, &status); ok(rc, "AccessCheck error %d\n", GetLastError());todo_wine { ok(status == 1, "expected 1, got %d\n", status); ok(granted == FILE_DELETE_CHILD, "expected FILE_DELETE_CHILD, got %#x\n", granted);} granted = 0xdeadbeef; status = 0xdeadbeef; SetLastError(0xdeadbeef); rc = AccessCheck(sd, token, 0x1ff, &mapping, &priv_set, &priv_set_len, &granted, &status); ok(rc, "AccessCheck error %d\n", GetLastError());todo_wine { ok(status == 1, "expected 1, got %d\n", status); ok(granted == 0x1ff, "expected 0x1ff, got %#x\n", granted);} granted = 0xdeadbeef; status = 0xdeadbeef; SetLastError(0xdeadbeef); rc = AccessCheck(sd, token, FILE_ALL_ACCESS, &mapping, &priv_set, &priv_set_len, &granted, &status); ok(rc, "AccessCheck error %d\n", GetLastError());todo_wine { ok(status == 1, "expected 1, got %d\n", status); ok(granted == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#x\n", granted);} SetLastError(0xdeadbeef); rc = DeleteFileA(file); ok(!rc, "DeleteFile should fail\n"); ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); SetLastError(0xdeadbeef); rc = SetFileAttributesA(file, FILE_ATTRIBUTE_ARCHIVE); ok(rc, "SetFileAttributes error %d\n", GetLastError()); SetLastError(0xdeadbeef); rc = DeleteFileA(file); ok(rc, "DeleteFile error %d\n", GetLastError());
CloseHandle(token); HeapFree(GetProcessHeap(), 0, sd);}
static void test_AccessCheck(void){ PSID EveryoneSid = NULL, AdminSid = NULL, UsersSid = NULL; PACL Acl = NULL; SECURITY_DESCRIPTOR *SecurityDescriptor = NULL; SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY }; SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY }; GENERIC_MAPPING Mapping = { KEY_READ, KEY_WRITE, KEY_EXECUTE, KEY_ALL_ACCESS }; ACCESS_MASK Access; BOOL AccessStatus; HANDLE Token; HANDLE ProcessToken; BOOL ret; DWORD PrivSetLen; PRIVILEGE_SET *PrivSet; BOOL res; HMODULE NtDllModule; BOOLEAN Enabled; DWORD err; NTSTATUS ntret, ntAccessStatus;
NtDllModule = GetModuleHandleA("ntdll.dll"); if (!NtDllModule) { skip("not running on NT, skipping test\n"); return; } pRtlAdjustPrivilege = (void *)GetProcAddress(NtDllModule, "RtlAdjustPrivilege"); if (!pRtlAdjustPrivilege) { win_skip("missing RtlAdjustPrivilege, skipping test\n"); return; }
Acl = HeapAlloc(GetProcessHeap(), 0, 256); res = InitializeAcl(Acl, 256, ACL_REVISION); if(!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) { skip("ACLs not implemented - skipping tests\n"); HeapFree(GetProcessHeap(), 0, Acl); return; } ok(res, "InitializeAcl failed with error %d\n", GetLastError());
res = AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid); ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
res = AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdminSid); ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
res = AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &UsersSid); ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
SecurityDescriptor = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
res = InitializeSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION); ok(res, "InitializeSecurityDescriptor failed with error %d\n", GetLastError());
res = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE); ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
PrivSetLen = FIELD_OFFSET(PRIVILEGE_SET, Privilege[16]); PrivSet = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, PrivSetLen); PrivSet->PrivilegeCount = 16;
res = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE|TOKEN_QUERY, &ProcessToken); ok(res, "OpenProcessToken failed with error %d\n", GetLastError());
pRtlAdjustPrivilege(SE_SECURITY_PRIVILEGE, FALSE, TRUE, &Enabled);
res = DuplicateToken(ProcessToken, SecurityImpersonation, &Token); ok(res, "DuplicateToken failed with error %d\n", GetLastError());
/* SD without owner/group */ SetLastError(0xdeadbeef); Access = AccessStatus = 0x1abe11ed; ret = AccessCheck(SecurityDescriptor, Token, KEY_QUERY_VALUE, &Mapping, PrivSet, &PrivSetLen, &Access, &AccessStatus); err = GetLastError(); ok(!ret && err == ERROR_INVALID_SECURITY_DESCR, "AccessCheck should have " "failed with ERROR_INVALID_SECURITY_DESCR, instead of %d\n", err); ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, "Access and/or AccessStatus were changed!\n");
/* Set owner and group */ res = SetSecurityDescriptorOwner(SecurityDescriptor, AdminSid, FALSE); ok(res, "SetSecurityDescriptorOwner failed with error %d\n", GetLastError()); res = SetSecurityDescriptorGroup(SecurityDescriptor, UsersSid, TRUE); ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError());
/* Generic access mask */ SetLastError(0xdeadbeef); Access = AccessStatus = 0x1abe11ed; ret = AccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping, PrivSet, &PrivSetLen, &Access, &AccessStatus); err = GetLastError(); ok(!ret && err == ERROR_GENERIC_NOT_MAPPED, "AccessCheck should have failed " "with ERROR_GENERIC_NOT_MAPPED, instead of %d\n", err); ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, "Access and/or AccessStatus were changed!\n");
/* Generic access mask - no privilegeset buffer */ SetLastError(0xdeadbeef); Access = AccessStatus = 0x1abe11ed; ret = AccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping, NULL, &PrivSetLen, &Access, &AccessStatus); err = GetLastError(); ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have failed " "with ERROR_NOACCESS, instead of %d\n", err); ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, "Access and/or AccessStatus were changed!\n");
/* Generic access mask - no returnlength */ SetLastError(0xdeadbeef); Access = AccessStatus = 0x1abe11ed; ret = AccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping, PrivSet, NULL, &Access, &AccessStatus); err = GetLastError(); ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have failed " "with ERROR_NOACCESS, instead of %d\n", err); ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, "Access and/or AccessStatus were changed!\n");
/* Generic access mask - no privilegeset buffer, no returnlength */ SetLastError(0xdeadbeef); Access = AccessStatus = 0x1abe11ed; ret = AccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping, NULL, NULL, &Access, &AccessStatus); err = GetLastError(); ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have failed " "with ERROR_NOACCESS, instead of %d\n", err); ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, "Access and/or AccessStatus were changed!\n");
/* sd with no dacl present */ Access = AccessStatus = 0x1abe11ed; ret = SetSecurityDescriptorDacl(SecurityDescriptor, FALSE, NULL, FALSE); ok(ret, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError()); ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, PrivSet, &PrivSetLen, &Access, &AccessStatus); ok(ret, "AccessCheck failed with error %d\n", GetLastError()); ok(AccessStatus && (Access == KEY_READ), "AccessCheck failed to grant access with error %d\n", GetLastError());
/* sd with no dacl present - no privilegeset buffer */ SetLastError(0xdeadbeef); Access = AccessStatus = 0x1abe11ed; ret = AccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping, NULL, &PrivSetLen, &Access, &AccessStatus); err = GetLastError(); ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have failed " "with ERROR_NOACCESS, instead of %d\n", err); ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, "Access and/or AccessStatus were changed!\n");
if(pNtAccessCheck) { /* Generic access mask - no privilegeset buffer */ SetLastError(0xdeadbeef); Access = ntAccessStatus = 0x1abe11ed; ntret = pNtAccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping, NULL, &PrivSetLen, &Access, &ntAccessStatus); err = GetLastError(); ok(ntret == STATUS_ACCESS_VIOLATION, "NtAccessCheck should have failed with STATUS_ACCESS_VIOLATION, got %x\n", ntret); ok(err == 0xdeadbeef, "NtAccessCheck shouldn't set last error, got %d\n", err); ok(Access == 0x1abe11ed && ntAccessStatus == 0x1abe11ed, "Access and/or AccessStatus were changed!\n");
/* Generic access mask - no returnlength */ SetLastError(0xdeadbeef); Access = ntAccessStatus = 0x1abe11ed; ntret = pNtAccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping, PrivSet, NULL, &Access, &ntAccessStatus); err = GetLastError(); ok(ntret == STATUS_ACCESS_VIOLATION, "NtAccessCheck should have failed with STATUS_ACCESS_VIOLATION, got %x\n", ntret); ok(err == 0xdeadbeef, "NtAccessCheck shouldn't set last error, got %d\n", err); ok(Access == 0x1abe11ed && ntAccessStatus == 0x1abe11ed, "Access and/or AccessStatus were changed!\n");
/* Generic access mask - no privilegeset buffer, no returnlength */ SetLastError(0xdeadbeef); Access = ntAccessStatus = 0x1abe11ed; ntret = pNtAccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping, NULL, NULL, &Access, &ntAccessStatus); err = GetLastError(); ok(ntret == STATUS_ACCESS_VIOLATION, "NtAccessCheck should have failed with STATUS_ACCESS_VIOLATION, got %x\n", ntret); ok(err == 0xdeadbeef, "NtAccessCheck shouldn't set last error, got %d\n", err); ok(Access == 0x1abe11ed && ntAccessStatus == 0x1abe11ed, "Access and/or AccessStatus were changed!\n"); } else win_skip("NtAccessCheck unavailable. Skipping.\n");
/* sd with NULL dacl */ Access = AccessStatus = 0x1abe11ed; ret = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, NULL, FALSE); ok(ret, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError()); ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, PrivSet, &PrivSetLen, &Access, &AccessStatus); ok(ret, "AccessCheck failed with error %d\n", GetLastError()); ok(AccessStatus && (Access == KEY_READ), "AccessCheck failed to grant access with error %d\n", GetLastError()); ret = AccessCheck(SecurityDescriptor, Token, MAXIMUM_ALLOWED, &Mapping, PrivSet, &PrivSetLen, &Access, &AccessStatus); ok(ret, "AccessCheck failed with error %d\n", GetLastError()); ok(AccessStatus && (Access == KEY_ALL_ACCESS), "AccessCheck failed to grant access with error %d\n", GetLastError());
/* sd with blank dacl */ ret = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE); ok(ret, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError()); ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, PrivSet, &PrivSetLen, &Access, &AccessStatus); ok(ret, "AccessCheck failed with error %d\n", GetLastError()); err = GetLastError(); ok(!AccessStatus && err == ERROR_ACCESS_DENIED, "AccessCheck should have failed " "with ERROR_ACCESS_DENIED, instead of %d\n", err); ok(!Access, "Should have failed to grant any access, got 0x%08x\n", Access);
res = AddAccessAllowedAce(Acl, ACL_REVISION, KEY_READ, EveryoneSid); ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
res = AddAccessDeniedAce(Acl, ACL_REVISION, KEY_SET_VALUE, AdminSid); ok(res, "AddAccessDeniedAce failed with error %d\n", GetLastError());
/* sd with dacl */ Access = AccessStatus = 0x1abe11ed; ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, PrivSet, &PrivSetLen, &Access, &AccessStatus); ok(ret, "AccessCheck failed with error %d\n", GetLastError()); ok(AccessStatus && (Access == KEY_READ), "AccessCheck failed to grant access with error %d\n", GetLastError());
ret = AccessCheck(SecurityDescriptor, Token, MAXIMUM_ALLOWED, &Mapping, PrivSet, &PrivSetLen, &Access, &AccessStatus); ok(ret, "AccessCheck failed with error %d\n", GetLastError()); ok(AccessStatus, "AccessCheck failed to grant any access with error %d\n", GetLastError()); trace("AccessCheck with MAXIMUM_ALLOWED got Access 0x%08x\n", Access);
/* Null PrivSet with null PrivSetLen pointer */ SetLastError(0xdeadbeef); Access = AccessStatus = 0x1abe11ed; ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, NULL, NULL, &Access, &AccessStatus); err = GetLastError(); ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have " "failed with ERROR_NOACCESS, instead of %d\n", err); ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, "Access and/or AccessStatus were changed!\n");
/* Null PrivSet with zero PrivSetLen */ SetLastError(0xdeadbeef); Access = AccessStatus = 0x1abe11ed; PrivSetLen = 0; ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, 0, &PrivSetLen, &Access, &AccessStatus); err = GetLastError(); ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have " "failed with ERROR_INSUFFICIENT_BUFFER, instead of %d\n", err); ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen); ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, "Access and/or AccessStatus were changed!\n");
/* Null PrivSet with insufficient PrivSetLen */ SetLastError(0xdeadbeef); Access = AccessStatus = 0x1abe11ed; PrivSetLen = 1; ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, 0, &PrivSetLen, &Access, &AccessStatus); err = GetLastError(); ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have " "failed with ERROR_NOACCESS, instead of %d\n", err); ok(PrivSetLen == 1, "PrivSetLen returns %d\n", PrivSetLen); ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, "Access and/or AccessStatus were changed!\n");
/* Null PrivSet with insufficient PrivSetLen */ SetLastError(0xdeadbeef); Access = AccessStatus = 0x1abe11ed; PrivSetLen = sizeof(PRIVILEGE_SET) - 1; ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, 0, &PrivSetLen, &Access, &AccessStatus); err = GetLastError(); ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have " "failed with ERROR_NOACCESS, instead of %d\n", err); ok(PrivSetLen == sizeof(PRIVILEGE_SET) - 1, "PrivSetLen returns %d\n", PrivSetLen); ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, "Access and/or AccessStatus were changed!\n");
/* Null PrivSet with minimal sufficient PrivSetLen */ SetLastError(0xdeadbeef); Access = AccessStatus = 0x1abe11ed; PrivSetLen = sizeof(PRIVILEGE_SET); ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, 0, &PrivSetLen, &Access, &AccessStatus); err = GetLastError(); ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have " "failed with ERROR_NOACCESS, instead of %d\n", err); ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen); ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, "Access and/or AccessStatus were changed!\n");
/* Valid PrivSet with zero PrivSetLen */ SetLastError(0xdeadbeef); Access = AccessStatus = 0x1abe11ed; PrivSetLen = 0; ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, PrivSet, &PrivSetLen, &Access, &AccessStatus); err = GetLastError(); ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have " "failed with ERROR_INSUFFICIENT_BUFFER, instead of %d\n", err); ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen); ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, "Access and/or AccessStatus were changed!\n");
/* Valid PrivSet with insufficient PrivSetLen */ SetLastError(0xdeadbeef); Access = AccessStatus = 0x1abe11ed; PrivSetLen = 1; ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, PrivSet, &PrivSetLen, &Access, &AccessStatus); err = GetLastError();todo_wine ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have " "failed with ERROR_INSUFFICIENT_BUFFER, instead of %d\n", err);todo_wine ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen); ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, "Access and/or AccessStatus were changed!\n");
/* Valid PrivSet with insufficient PrivSetLen */ SetLastError(0xdeadbeef); Access = AccessStatus = 0x1abe11ed; PrivSetLen = sizeof(PRIVILEGE_SET) - 1; ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, PrivSet, &PrivSetLen, &Access, &AccessStatus); err = GetLastError();todo_wine ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have " "failed with ERROR_INSUFFICIENT_BUFFER, instead of %d\n", err);todo_wine ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen);todo_wine ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, "Access and/or AccessStatus were changed!\n");
/* Valid PrivSet with minimal sufficient PrivSetLen */ SetLastError(0xdeadbeef); Access = AccessStatus = 0x1abe11ed; PrivSetLen = sizeof(PRIVILEGE_SET); memset(PrivSet, 0xcc, PrivSetLen); ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, PrivSet, &PrivSetLen, &Access, &AccessStatus); err = GetLastError(); ok(ret, "AccessCheck failed with error %d\n", GetLastError());todo_wine ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen); ok(AccessStatus && (Access == KEY_READ), "AccessCheck failed to grant access with error %d\n", GetLastError()); ok(PrivSet->PrivilegeCount == 0, "PrivilegeCount returns %d, expects 0\n", PrivSet->PrivilegeCount);
/* Valid PrivSet with sufficient PrivSetLen */ SetLastError(0xdeadbeef); Access = AccessStatus = 0x1abe11ed; PrivSetLen = sizeof(PRIVILEGE_SET) + 1; memset(PrivSet, 0xcc, PrivSetLen); ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, PrivSet, &PrivSetLen, &Access, &AccessStatus); err = GetLastError(); ok(ret, "AccessCheck failed with error %d\n", GetLastError());todo_wine ok(PrivSetLen == sizeof(PRIVILEGE_SET) + 1, "PrivSetLen returns %d\n", PrivSetLen); ok(AccessStatus && (Access == KEY_READ), "AccessCheck failed to grant access with error %d\n", GetLastError()); ok(PrivSet->PrivilegeCount == 0, "PrivilegeCount returns %d, expects 0\n", PrivSet->PrivilegeCount);
PrivSetLen = FIELD_OFFSET(PRIVILEGE_SET, Privilege[16]);
/* Null PrivSet with valid PrivSetLen */ SetLastError(0xdeadbeef); Access = AccessStatus = 0x1abe11ed; ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, 0, &PrivSetLen, &Access, &AccessStatus); err = GetLastError(); ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have " "failed with ERROR_NOACCESS, instead of %d\n", err); ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, "Access and/or AccessStatus were changed!\n");
/* Access denied by SD */ SetLastError(0xdeadbeef); Access = AccessStatus = 0x1abe11ed; ret = AccessCheck(SecurityDescriptor, Token, KEY_WRITE, &Mapping, PrivSet, &PrivSetLen, &Access, &AccessStatus); ok(ret, "AccessCheck failed with error %d\n", GetLastError()); err = GetLastError(); ok(!AccessStatus && err == ERROR_ACCESS_DENIED, "AccessCheck should have failed " "with ERROR_ACCESS_DENIED, instead of %d\n", err); ok(!Access, "Should have failed to grant any access, got 0x%08x\n", Access);
SetLastError(0xdeadbeef); PrivSet->PrivilegeCount = 16; ret = AccessCheck(SecurityDescriptor, Token, ACCESS_SYSTEM_SECURITY, &Mapping, PrivSet, &PrivSetLen, &Access, &AccessStatus); ok(ret && !AccessStatus && GetLastError() == ERROR_PRIVILEGE_NOT_HELD, "AccessCheck should have failed with ERROR_PRIVILEGE_NOT_HELD, instead of %d\n", GetLastError());
ret = ImpersonateLoggedOnUser(Token); ok(ret, "ImpersonateLoggedOnUser failed with error %d\n", GetLastError()); ret = pRtlAdjustPrivilege(SE_SECURITY_PRIVILEGE, TRUE, TRUE, &Enabled); if (!ret) { /* Valid PrivSet with zero PrivSetLen */ SetLastError(0xdeadbeef); Access = AccessStatus = 0x1abe11ed; PrivSetLen = 0; ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, PrivSet, &PrivSetLen, &Access, &AccessStatus); err = GetLastError(); ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have " "failed with ERROR_INSUFFICIENT_BUFFER, instead of %d\n", err); ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen); ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, "Access and/or AccessStatus were changed!\n");
/* Valid PrivSet with insufficient PrivSetLen */ SetLastError(0xdeadbeef); Access = AccessStatus = 0x1abe11ed; PrivSetLen = sizeof(PRIVILEGE_SET) - 1; ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, PrivSet, &PrivSetLen, &Access, &AccessStatus); err = GetLastError(); todo_wine ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have " "failed with ERROR_INSUFFICIENT_BUFFER, instead of %d\n", err); todo_wine ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen); todo_wine ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, "Access and/or AccessStatus were changed!\n");
/* Valid PrivSet with minimal sufficient PrivSetLen */ SetLastError(0xdeadbeef); Access = AccessStatus = 0x1abe11ed; PrivSetLen = sizeof(PRIVILEGE_SET); memset(PrivSet, 0xcc, PrivSetLen); ret = AccessCheck(SecurityDescriptor, Token, ACCESS_SYSTEM_SECURITY, &Mapping, PrivSet, &PrivSetLen, &Access, &AccessStatus); ok(ret && AccessStatus && GetLastError() == 0xdeadbeef, "AccessCheck should have succeeded, error %d\n", GetLastError()); ok(Access == ACCESS_SYSTEM_SECURITY, "Access should be equal to ACCESS_SYSTEM_SECURITY instead of 0x%08x\n", Access); ok(PrivSet->PrivilegeCount == 1, "PrivilegeCount returns %d, expects 1\n", PrivSet->PrivilegeCount);
/* Valid PrivSet with large PrivSetLen */ SetLastError(0xdeadbeef); Access = AccessStatus = 0x1abe11ed; PrivSetLen = FIELD_OFFSET(PRIVILEGE_SET, Privilege[16]); memset(PrivSet, 0xcc, PrivSetLen); ret = AccessCheck(SecurityDescriptor, Token, ACCESS_SYSTEM_SECURITY, &Mapping, PrivSet, &PrivSetLen, &Access, &AccessStatus); ok(ret && AccessStatus && GetLastError() == 0xdeadbeef, "AccessCheck should have succeeded, error %d\n", GetLastError()); ok(Access == ACCESS_SYSTEM_SECURITY, "Access should be equal to ACCESS_SYSTEM_SECURITY instead of 0x%08x\n", Access); ok(PrivSet->PrivilegeCount == 1, "PrivilegeCount returns %d, expects 1\n", PrivSet->PrivilegeCount); } else trace("Couldn't get SE_SECURITY_PRIVILEGE (0x%08x), skipping ACCESS_SYSTEM_SECURITY test\n", ret); ret = RevertToSelf(); ok(ret, "RevertToSelf failed with error %d\n", GetLastError());
/* test INHERIT_ONLY_ACE */ ret = InitializeAcl(Acl, 256, ACL_REVISION); ok(ret, "InitializeAcl failed with error %d\n", GetLastError());
/* NT doesn't have AddAccessAllowedAceEx. Skipping this call/test doesn't influence * the next ones. */ if (pAddAccessAllowedAceEx) { ret = pAddAccessAllowedAceEx(Acl, ACL_REVISION, INHERIT_ONLY_ACE, KEY_READ, EveryoneSid); ok(ret, "AddAccessAllowedAceEx failed with error %d\n", GetLastError()); } else win_skip("AddAccessAllowedAceEx is not available\n");
ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, PrivSet, &PrivSetLen, &Access, &AccessStatus); ok(ret, "AccessCheck failed with error %d\n", GetLastError()); err = GetLastError(); ok(!AccessStatus && err == ERROR_ACCESS_DENIED, "AccessCheck should have failed " "with ERROR_ACCESS_DENIED, instead of %d\n", err); ok(!Access, "Should have failed to grant any access, got 0x%08x\n", Access);
CloseHandle(Token);
res = DuplicateToken(ProcessToken, SecurityAnonymous, &Token); ok(res, "DuplicateToken failed with error %d\n", GetLastError());
SetLastError(0xdeadbeef); ret = AccessCheck(SecurityDescriptor, Token, MAXIMUM_ALLOWED, &Mapping, PrivSet, &PrivSetLen, &Access, &AccessStatus); err = GetLastError(); ok(!ret && err == ERROR_BAD_IMPERSONATION_LEVEL, "AccessCheck should have failed " "with ERROR_BAD_IMPERSONATION_LEVEL, instead of %d\n", err);
CloseHandle(Token);
SetLastError(0xdeadbeef); ret = AccessCheck(SecurityDescriptor, ProcessToken, KEY_READ, &Mapping, PrivSet, &PrivSetLen, &Access, &AccessStatus); err = GetLastError(); ok(!ret && err == ERROR_NO_IMPERSONATION_TOKEN, "AccessCheck should have failed " "with ERROR_NO_IMPERSONATION_TOKEN, instead of %d\n", err);
CloseHandle(ProcessToken);
if (EveryoneSid) FreeSid(EveryoneSid); if (AdminSid) FreeSid(AdminSid); if (UsersSid) FreeSid(UsersSid); HeapFree(GetProcessHeap(), 0, Acl); HeapFree(GetProcessHeap(), 0, SecurityDescriptor); HeapFree(GetProcessHeap(), 0, PrivSet);}
/* test GetTokenInformation for the various attributes */static void test_token_attr(void){ HANDLE Token, ImpersonationToken; DWORD Size, Size2; TOKEN_PRIVILEGES *Privileges; TOKEN_GROUPS *Groups; TOKEN_USER *User; TOKEN_DEFAULT_DACL *Dacl; BOOL ret; DWORD i, GLE; LPSTR SidString; SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; ACL *acl;
/* cygwin-like use case */ SetLastError(0xdeadbeef); ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &Token); if(!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) { win_skip("OpenProcessToken is not implemented\n"); return; } ok(ret, "OpenProcessToken failed with error %d\n", GetLastError()); if (ret) { DWORD buf[256]; /* GetTokenInformation wants a dword-aligned buffer */ Size = sizeof(buf); ret = GetTokenInformation(Token, TokenUser,(void*)buf, Size, &Size); ok(ret, "GetTokenInformation failed with error %d\n", GetLastError()); Size = sizeof(ImpersonationLevel); ret = GetTokenInformation(Token, TokenImpersonationLevel, &ImpersonationLevel, Size, &Size); GLE = GetLastError(); ok(!ret && (GLE == ERROR_INVALID_PARAMETER), "GetTokenInformation(TokenImpersonationLevel) on primary token should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GLE); CloseHandle(Token); }
SetLastError(0xdeadbeef); ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &Token); ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
/* groups */ /* insufficient buffer length */ SetLastError(0xdeadbeef); Size2 = 0; ret = GetTokenInformation(Token, TokenGroups, NULL, 0, &Size2); ok(Size2 > 1, "got %d\n", Size2); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "%d with error %d\n", ret, GetLastError()); Size2 -= 1; Groups = HeapAlloc(GetProcessHeap(), 0, Size2); memset(Groups, 0xcc, Size2); Size = 0; ret = GetTokenInformation(Token, TokenGroups, Groups, Size2, &Size); ok(Size > 1, "got %d\n", Size); ok((!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER) || broken(ret) /* wow64 */, "%d with error %d\n", ret, GetLastError()); if(!ret) ok(*((BYTE*)Groups) == 0xcc, "buffer altered\n");
HeapFree(GetProcessHeap(), 0, Groups);
SetLastError(0xdeadbeef); ret = GetTokenInformation(Token, TokenGroups, NULL, 0, &Size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenGroups) %s with error %d\n", ret ? "succeeded" : "failed", GetLastError()); Groups = HeapAlloc(GetProcessHeap(), 0, Size); SetLastError(0xdeadbeef); ret = GetTokenInformation(Token, TokenGroups, Groups, Size, &Size); ok(ret, "GetTokenInformation(TokenGroups) failed with error %d\n", GetLastError()); ok(GetLastError() == 0xdeadbeef, "GetTokenInformation shouldn't have set last error to %d\n", GetLastError()); trace("TokenGroups:\n"); for (i = 0; i < Groups->GroupCount; i++) { DWORD NameLength = 255; CHAR Name[255]; DWORD DomainLength = 255; CHAR Domain[255]; SID_NAME_USE SidNameUse; Name[0] = '\0'; Domain[0] = '\0'; ret = LookupAccountSidA(NULL, Groups->Groups[i].Sid, Name, &NameLength, Domain, &DomainLength, &SidNameUse); if (ret) { ConvertSidToStringSidA(Groups->Groups[i].Sid, &SidString); trace("%s, %s\\%s use: %d attr: 0x%08x\n", SidString, Domain, Name, SidNameUse, Groups->Groups[i].Attributes); LocalFree(SidString); } else trace("attr: 0x%08x LookupAccountSid failed with error %d\n", Groups->Groups[i].Attributes, GetLastError()); } HeapFree(GetProcessHeap(), 0, Groups);
/* user */ ret = GetTokenInformation(Token, TokenUser, NULL, 0, &Size); ok(!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER), "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError()); User = HeapAlloc(GetProcessHeap(), 0, Size); ret = GetTokenInformation(Token, TokenUser, User, Size, &Size); ok(ret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
ConvertSidToStringSidA(User->User.Sid, &SidString); trace("TokenUser: %s attr: 0x%08x\n", SidString, User->User.Attributes); LocalFree(SidString); HeapFree(GetProcessHeap(), 0, User);
/* logon */ ret = GetTokenInformation(Token, TokenLogonSid, NULL, 0, &Size); if (!ret && (GetLastError() == ERROR_INVALID_PARAMETER)) todo_wine win_skip("TokenLogonSid not supported. Skipping tests\n"); else { ok(!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER), "GetTokenInformation(TokenLogonSid) failed with error %d\n", GetLastError()); Groups = HeapAlloc(GetProcessHeap(), 0, Size); ret = GetTokenInformation(Token, TokenLogonSid, Groups, Size, &Size); ok(ret, "GetTokenInformation(TokenLogonSid) failed with error %d\n", GetLastError()); if (ret) { ok(Groups->GroupCount == 1, "got %d\n", Groups->GroupCount); if(Groups->GroupCount == 1) { ConvertSidToStringSidA(Groups->Groups[0].Sid, &SidString); trace("TokenLogon: %s\n", SidString); LocalFree(SidString);
/* S-1-5-5-0-XXXXXX */ ret = IsWellKnownSid(Groups->Groups[0].Sid, WinLogonIdsSid); ok(ret, "Unknown SID\n"); } }
HeapFree(GetProcessHeap(), 0, Groups); }
/* privileges */ ret = GetTokenInformation(Token, TokenPrivileges, NULL, 0, &Size); ok(!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER), "GetTokenInformation(TokenPrivileges) failed with error %d\n", GetLastError()); Privileges = HeapAlloc(GetProcessHeap(), 0, Size); ret = GetTokenInformation(Token, TokenPrivileges, Privileges, Size, &Size); ok(ret, "GetTokenInformation(TokenPrivileges) failed with error %d\n", GetLastError()); trace("TokenPrivileges:\n"); for (i = 0; i < Privileges->PrivilegeCount; i++) { CHAR Name[256]; DWORD NameLen = sizeof(Name)/sizeof(Name[0]); LookupPrivilegeNameA(NULL, &Privileges->Privileges[i].Luid, Name, &NameLen); trace("\t%s, 0x%x\n", Name, Privileges->Privileges[i].Attributes); } HeapFree(GetProcessHeap(), 0, Privileges);
ret = DuplicateToken(Token, SecurityAnonymous, &ImpersonationToken); ok(ret, "DuplicateToken failed with error %d\n", GetLastError());
Size = sizeof(ImpersonationLevel); ret = GetTokenInformation(ImpersonationToken, TokenImpersonationLevel, &ImpersonationLevel, Size, &Size); ok(ret, "GetTokenInformation(TokenImpersonationLevel) failed with error %d\n", GetLastError()); ok(ImpersonationLevel == SecurityAnonymous, "ImpersonationLevel should have been SecurityAnonymous instead of %d\n", ImpersonationLevel);
CloseHandle(ImpersonationToken);
/* default dacl */ ret = GetTokenInformation(Token, TokenDefaultDacl, NULL, 0, &Size); ok(!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER), "GetTokenInformation(TokenDefaultDacl) failed with error %u\n", GetLastError());
Dacl = HeapAlloc(GetProcessHeap(), 0, Size); ret = GetTokenInformation(Token, TokenDefaultDacl, Dacl, Size, &Size); ok(ret, "GetTokenInformation(TokenDefaultDacl) failed with error %u\n", GetLastError());
SetLastError(0xdeadbeef); ret = SetTokenInformation(Token, TokenDefaultDacl, NULL, 0); GLE = GetLastError(); ok(!ret, "SetTokenInformation(TokenDefaultDacl) succeeded\n"); ok(GLE == ERROR_BAD_LENGTH, "expected ERROR_BAD_LENGTH got %u\n", GLE);
SetLastError(0xdeadbeef); ret = SetTokenInformation(Token, TokenDefaultDacl, NULL, Size); GLE = GetLastError(); ok(!ret, "SetTokenInformation(TokenDefaultDacl) succeeded\n"); ok(GLE == ERROR_NOACCESS, "expected ERROR_NOACCESS got %u\n", GLE);
acl = Dacl->DefaultDacl; Dacl->DefaultDacl = NULL;
ret = SetTokenInformation(Token, TokenDefaultDacl, Dacl, Size); ok(ret, "SetTokenInformation(TokenDefaultDacl) succeeded\n");
Size2 = 0; Dacl->DefaultDacl = (ACL *)0xdeadbeef; ret = GetTokenInformation(Token, TokenDefaultDacl, Dacl, Size, &Size2); ok(ret, "GetTokenInformation(TokenDefaultDacl) failed with error %u\n", GetLastError()); ok(Dacl->DefaultDacl == NULL, "expected NULL, got %p\n", Dacl->DefaultDacl); ok(Size2 == sizeof(TOKEN_DEFAULT_DACL) || broken(Size2 == 2*sizeof(TOKEN_DEFAULT_DACL)), /* WoW64 */ "got %u expected sizeof(TOKEN_DEFAULT_DACL)\n", Size2);
Dacl->DefaultDacl = acl; ret = SetTokenInformation(Token, TokenDefaultDacl, Dacl, Size); ok(ret, "SetTokenInformation(TokenDefaultDacl) failed with error %u\n", GetLastError());
if (Size2 == sizeof(TOKEN_DEFAULT_DACL)) { ret = GetTokenInformation(Token, TokenDefaultDacl, Dacl, Size, &Size2); ok(ret, "GetTokenInformation(TokenDefaultDacl) failed with error %u\n", GetLastError()); } else win_skip("TOKEN_DEFAULT_DACL size too small on WoW64\n");
HeapFree(GetProcessHeap(), 0, Dacl); CloseHandle(Token);}
static void test_GetTokenInformation(void){ DWORD is_app_container, size; HANDLE token; BOOL ret;
ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token); ok(ret, "OpenProcessToken failed: %u\n", GetLastError());
size = 0; is_app_container = 0xdeadbeef; ret = GetTokenInformation(token, TokenIsAppContainer, &is_app_container, sizeof(is_app_container), &size); ok(ret || broken(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_INVALID_FUNCTION), /* pre-win8 */ "GetTokenInformation failed: %u\n", GetLastError()); if(ret) { ok(size == sizeof(is_app_container), "size = %u\n", size); ok(!is_app_container, "is_app_container = %x\n", is_app_container); }
CloseHandle(token);}
typedef union _MAX_SID{ SID sid; char max[SECURITY_MAX_SID_SIZE];} MAX_SID;
static void test_sid_str(PSID * sid){ char *str_sid; BOOL ret = ConvertSidToStringSidA(sid, &str_sid); ok(ret, "ConvertSidToStringSidA() failed: %d\n", GetLastError()); if (ret) { char account[MAX_PATH], domain[MAX_PATH]; SID_NAME_USE use; DWORD acc_size = MAX_PATH; DWORD dom_size = MAX_PATH; ret = LookupAccountSidA (NULL, sid, account, &acc_size, domain, &dom_size, &use); ok(ret || GetLastError() == ERROR_NONE_MAPPED, "LookupAccountSid(%s) failed: %d\n", str_sid, GetLastError()); if (ret) trace(" %s %s\\%s %d\n", str_sid, domain, account, use); else if (GetLastError() == ERROR_NONE_MAPPED) trace(" %s couldn't be mapped\n", str_sid); LocalFree(str_sid); }}
static const struct well_known_sid_value{ BOOL without_domain; const char *sid_string;} well_known_sid_values[] = {/* 0 */ {TRUE, "S-1-0-0"}, {TRUE, "S-1-1-0"}, {TRUE, "S-1-2-0"}, {TRUE, "S-1-3-0"},/* 4 */ {TRUE, "S-1-3-1"}, {TRUE, "S-1-3-2"}, {TRUE, "S-1-3-3"}, {TRUE, "S-1-5"},/* 8 */ {FALSE, "S-1-5-1"}, {TRUE, "S-1-5-2"}, {TRUE, "S-1-5-3"}, {TRUE, "S-1-5-4"},/* 12 */ {TRUE, "S-1-5-6"}, {TRUE, "S-1-5-7"}, {TRUE, "S-1-5-8"}, {TRUE, "S-1-5-9"},/* 16 */ {TRUE, "S-1-5-10"}, {TRUE, "S-1-5-11"}, {TRUE, "S-1-5-12"}, {TRUE, "S-1-5-13"},/* 20 */ {TRUE, "S-1-5-14"}, {FALSE, NULL}, {TRUE, "S-1-5-18"}, {TRUE, "S-1-5-19"},/* 24 */ {TRUE, "S-1-5-20"}, {TRUE, "S-1-5-32"},/* 26 */ {FALSE, "S-1-5-32-544"}, {TRUE, "S-1-5-32-545"}, {TRUE, "S-1-5-32-546"},/* 29 */ {TRUE, "S-1-5-32-547"}, {TRUE, "S-1-5-32-548"}, {TRUE, "S-1-5-32-549"},/* 32 */ {TRUE, "S-1-5-32-550"}, {TRUE, "S-1-5-32-551"}, {TRUE, "S-1-5-32-552"},/* 35 */ {TRUE, "S-1-5-32-554"}, {TRUE, "S-1-5-32-555"}, {TRUE, "S-1-5-32-556"},/* 38 */ {FALSE, "S-1-5-21-12-23-34-45-56-500"}, {FALSE, "S-1-5-21-12-23-34-45-56-501"},/* 40 */ {FALSE, "S-1-5-21-12-23-34-45-56-502"}, {FALSE, "S-1-5-21-12-23-34-45-56-512"},/* 42 */ {FALSE, "S-1-5-21-12-23-34-45-56-513"}, {FALSE, "S-1-5-21-12-23-34-45-56-514"},/* 44 */ {FALSE, "S-1-5-21-12-23-34-45-56-515"}, {FALSE, "S-1-5-21-12-23-34-45-56-516"},/* 46 */ {FALSE, "S-1-5-21-12-23-34-45-56-517"}, {FALSE, "S-1-5-21-12-23-34-45-56-518"},/* 48 */ {FALSE, "S-1-5-21-12-23-34-45-56-519"}, {FALSE, "S-1-5-21-12-23-34-45-56-520"},/* 50 */ {FALSE, "S-1-5-21-12-23-34-45-56-553"},/* Added in Windows Server 2003 *//* 51 */ {TRUE, "S-1-5-64-10"}, {TRUE, "S-1-5-64-21"}, {TRUE, "S-1-5-64-14"},/* 54 */ {TRUE, "S-1-5-15"}, {TRUE, "S-1-5-1000"}, {FALSE, "S-1-5-32-557"},/* 57 */ {TRUE, "S-1-5-32-558"}, {TRUE, "S-1-5-32-559"}, {TRUE, "S-1-5-32-560"},/* 60 */ {TRUE, "S-1-5-32-561"}, {TRUE, "S-1-5-32-562"},/* Added in Windows Vista: *//* 62 */ {TRUE, "S-1-5-32-568"},/* 63 */ {TRUE, "S-1-5-17"}, {FALSE, "S-1-5-32-569"}, {TRUE, "S-1-16-0"},/* 66 */ {TRUE, "S-1-16-4096"}, {TRUE, "S-1-16-8192"}, {TRUE, "S-1-16-12288"},/* 69 */ {TRUE, "S-1-16-16384"}, {TRUE, "S-1-5-33"}, {TRUE, "S-1-3-4"},/* 72 */ {FALSE, "S-1-5-21-12-23-34-45-56-571"}, {FALSE, "S-1-5-21-12-23-34-45-56-572"},/* 74 */ {TRUE, "S-1-5-22"}, {FALSE, "S-1-5-21-12-23-34-45-56-521"}, {TRUE, "S-1-5-32-573"},/* 77 */ {FALSE, "S-1-5-21-12-23-34-45-56-498"}, {TRUE, "S-1-5-32-574"}, {TRUE, "S-1-16-8448"},/* 80 */ {FALSE, NULL}, {TRUE, "S-1-2-1"}, {TRUE, "S-1-5-65-1"}, {FALSE, NULL},/* 84 */ {TRUE, "S-1-15-2-1"},};
static void test_CreateWellKnownSid(void){ SID_IDENTIFIER_AUTHORITY ident = { SECURITY_NT_AUTHORITY }; PSID domainsid, sid; DWORD size, error; BOOL ret; unsigned int i;
if (!pCreateWellKnownSid) { win_skip("CreateWellKnownSid not available\n"); return; }
size = 0; SetLastError(0xdeadbeef); ret = pCreateWellKnownSid(WinInteractiveSid, NULL, NULL, &size); error = GetLastError(); ok(!ret, "CreateWellKnownSid succeeded\n"); ok(error == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", error); ok(size, "expected size > 0\n");
SetLastError(0xdeadbeef); ret = pCreateWellKnownSid(WinInteractiveSid, NULL, NULL, &size); error = GetLastError(); ok(!ret, "CreateWellKnownSid succeeded\n"); ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
sid = HeapAlloc(GetProcessHeap(), 0, size); ret = pCreateWellKnownSid(WinInteractiveSid, NULL, sid, &size); ok(ret, "CreateWellKnownSid failed %u\n", GetLastError()); HeapFree(GetProcessHeap(), 0, sid);
/* a domain sid usually have three subauthorities but we test that CreateWellKnownSid doesn't check it */ AllocateAndInitializeSid(&ident, 6, SECURITY_NT_NON_UNIQUE, 12, 23, 34, 45, 56, 0, 0, &domainsid);
for (i = 0; i < sizeof(well_known_sid_values)/sizeof(well_known_sid_values[0]); i++) { const struct well_known_sid_value *value = &well_known_sid_values[i]; char sid_buffer[SECURITY_MAX_SID_SIZE]; LPSTR str; DWORD cb;
if (value->sid_string == NULL) continue;
/* some SIDs aren't implemented by all Windows versions - detect it */ cb = sizeof(sid_buffer); if (!pCreateWellKnownSid(i, NULL, sid_buffer, &cb)) { skip("Well known SID %u not implemented\n", i); continue; }
cb = sizeof(sid_buffer); ok(pCreateWellKnownSid(i, value->without_domain ? NULL : domainsid, sid_buffer, &cb), "Couldn't create well known sid %u\n", i); expect_eq(GetSidLengthRequired(*GetSidSubAuthorityCount(sid_buffer)), cb, DWORD, "%d"); ok(IsValidSid(sid_buffer), "The sid is not valid\n"); ok(ConvertSidToStringSidA(sid_buffer, &str), "Couldn't convert SID to string\n"); ok(strcmp(str, value->sid_string) == 0, "%d: SID mismatch - expected %s, got %s\n", i, value->sid_string, str); LocalFree(str);
if (value->without_domain) { char buf2[SECURITY_MAX_SID_SIZE]; cb = sizeof(buf2); ok(pCreateWellKnownSid(i, domainsid, buf2, &cb), "Couldn't create well known sid %u with optional domain\n", i); expect_eq(GetSidLengthRequired(*GetSidSubAuthorityCount(sid_buffer)), cb, DWORD, "%d"); ok(memcmp(buf2, sid_buffer, cb) == 0, "SID create with domain is different than without (%u)\n", i); } }
FreeSid(domainsid);}
static void test_LookupAccountSid(void){ SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY }; CHAR accountA[MAX_PATH], domainA[MAX_PATH], usernameA[MAX_PATH]; DWORD acc_sizeA, dom_sizeA, user_sizeA; DWORD real_acc_sizeA, real_dom_sizeA; WCHAR accountW[MAX_PATH], domainW[MAX_PATH]; DWORD acc_sizeW, dom_sizeW; DWORD real_acc_sizeW, real_dom_sizeW; PSID pUsersSid = NULL; SID_NAME_USE use; BOOL ret; DWORD error, size, cbti = 0; MAX_SID max_sid; CHAR *str_sidA; int i; HANDLE hToken; PTOKEN_USER ptiUser = NULL;
/* native windows crashes if account size, domain size, or name use is NULL */
ret = AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &pUsersSid); ok(ret || (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED), "AllocateAndInitializeSid failed with error %d\n", GetLastError());
/* not running on NT so give up */ if (!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) return;
real_acc_sizeA = MAX_PATH; real_dom_sizeA = MAX_PATH; ret = LookupAccountSidA(NULL, pUsersSid, accountA, &real_acc_sizeA, domainA, &real_dom_sizeA, &use); ok(ret, "LookupAccountSidA() Expected TRUE, got FALSE\n");
/* try NULL account */ acc_sizeA = MAX_PATH; dom_sizeA = MAX_PATH; ret = LookupAccountSidA(NULL, pUsersSid, NULL, &acc_sizeA, domainA, &dom_sizeA, &use); ok(ret, "LookupAccountSidA() Expected TRUE, got FALSE\n");
/* try NULL domain */ acc_sizeA = MAX_PATH; dom_sizeA = MAX_PATH; ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, NULL, &dom_sizeA, &use); ok(ret, "LookupAccountSidA() Expected TRUE, got FALSE\n");
/* try a small account buffer */ acc_sizeA = 1; dom_sizeA = MAX_PATH; accountA[0] = 0; ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use); ok(!ret, "LookupAccountSidA() Expected FALSE got TRUE\n"); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "LookupAccountSidA() Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
/* try a 0 sized account buffer */ acc_sizeA = 0; dom_sizeA = MAX_PATH; accountA[0] = 0; LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use); /* this can fail or succeed depending on OS version but the size will always be returned */ ok(acc_sizeA == real_acc_sizeA + 1, "LookupAccountSidA() Expected acc_size = %u, got %u\n", real_acc_sizeA + 1, acc_sizeA);
/* try a 0 sized account buffer */ acc_sizeA = 0; dom_sizeA = MAX_PATH; LookupAccountSidA(NULL, pUsersSid, NULL, &acc_sizeA, domainA, &dom_sizeA, &use); /* this can fail or succeed depending on OS version but the size will always be returned */ ok(acc_sizeA == real_acc_sizeA + 1, "LookupAccountSid() Expected acc_size = %u, got %u\n", real_acc_sizeA + 1, acc_sizeA);
/* try a small domain buffer */ dom_sizeA = 1; acc_sizeA = MAX_PATH; accountA[0] = 0; ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use); ok(!ret, "LookupAccountSidA() Expected FALSE got TRUE\n"); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "LookupAccountSidA() Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
/* try a 0 sized domain buffer */ dom_sizeA = 0; acc_sizeA = MAX_PATH; accountA[0] = 0; LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use); /* this can fail or succeed depending on OS version but the size will always be returned */ ok(dom_sizeA == real_dom_sizeA + 1, "LookupAccountSidA() Expected dom_size = %u, got %u\n", real_dom_sizeA + 1, dom_sizeA);
/* try a 0 sized domain buffer */ dom_sizeA = 0; acc_sizeA = MAX_PATH; LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, NULL, &dom_sizeA, &use); /* this can fail or succeed depending on OS version but the size will always be returned */ ok(dom_sizeA == real_dom_sizeA + 1, "LookupAccountSidA() Expected dom_size = %u, got %u\n", real_dom_sizeA + 1, dom_sizeA);
real_acc_sizeW = MAX_PATH; real_dom_sizeW = MAX_PATH; ret = LookupAccountSidW(NULL, pUsersSid, accountW, &real_acc_sizeW, domainW, &real_dom_sizeW, &use); ok(ret, "LookupAccountSidW() Expected TRUE, got FALSE\n");
/* try an invalid system name */ real_acc_sizeA = MAX_PATH; real_dom_sizeA = MAX_PATH; ret = LookupAccountSidA("deepthought", pUsersSid, accountA, &real_acc_sizeA, domainA, &real_dom_sizeA, &use); ok(!ret, "LookupAccountSidA() Expected FALSE got TRUE\n"); ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE || GetLastError() == RPC_S_INVALID_NET_ADDR /* Vista */, "LookupAccountSidA() Expected RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR, got %u\n", GetLastError());
/* native windows crashes if domainW or accountW is NULL */
/* try a small account buffer */ acc_sizeW = 1; dom_sizeW = MAX_PATH; accountW[0] = 0; ret = LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use); ok(!ret, "LookupAccountSidW() Expected FALSE got TRUE\n"); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "LookupAccountSidW() Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
/* try a 0 sized account buffer */ acc_sizeW = 0; dom_sizeW = MAX_PATH; accountW[0] = 0; LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use); /* this can fail or succeed depending on OS version but the size will always be returned */ ok(acc_sizeW == real_acc_sizeW + 1, "LookupAccountSidW() Expected acc_size = %u, got %u\n", real_acc_sizeW + 1, acc_sizeW);
/* try a 0 sized account buffer */ acc_sizeW = 0; dom_sizeW = MAX_PATH; LookupAccountSidW(NULL, pUsersSid, NULL, &acc_sizeW, domainW, &dom_sizeW, &use); /* this can fail or succeed depending on OS version but the size will always be returned */ ok(acc_sizeW == real_acc_sizeW + 1, "LookupAccountSidW() Expected acc_size = %u, got %u\n", real_acc_sizeW + 1, acc_sizeW);
/* try a small domain buffer */ dom_sizeW = 1; acc_sizeW = MAX_PATH; accountW[0] = 0; ret = LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use); ok(!ret, "LookupAccountSidW() Expected FALSE got TRUE\n"); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "LookupAccountSidW() Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
/* try a 0 sized domain buffer */ dom_sizeW = 0; acc_sizeW = MAX_PATH; accountW[0] = 0; LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use); /* this can fail or succeed depending on OS version but the size will always be returned */ ok(dom_sizeW == real_dom_sizeW + 1, "LookupAccountSidW() Expected dom_size = %u, got %u\n", real_dom_sizeW + 1, dom_sizeW);
/* try a 0 sized domain buffer */ dom_sizeW = 0; acc_sizeW = MAX_PATH; LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, NULL, &dom_sizeW, &use); /* this can fail or succeed depending on OS version but the size will always be returned */ ok(dom_sizeW == real_dom_sizeW + 1, "LookupAccountSidW() Expected dom_size = %u, got %u\n", real_dom_sizeW + 1, dom_sizeW);
acc_sizeW = dom_sizeW = use = 0; SetLastError(0xdeadbeef); ret = LookupAccountSidW(NULL, pUsersSid, NULL, &acc_sizeW, NULL, &dom_sizeW, &use); error = GetLastError(); ok(!ret, "LookupAccountSidW failed %u\n", GetLastError()); ok(error == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", error); ok(acc_sizeW, "expected non-zero account size\n"); ok(dom_sizeW, "expected non-zero domain size\n"); ok(!use, "expected zero use %u\n", use);
FreeSid(pUsersSid);
/* Test LookupAccountSid with Sid retrieved from token information. This assumes this process is running under the account of the current user.*/ ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_DUPLICATE, &hToken); ok(ret, "OpenProcessToken failed with error %d\n", GetLastError()); ret = GetTokenInformation(hToken, TokenUser, NULL, 0, &cbti); ok(!ret, "GetTokenInformation failed with error %d\n", GetLastError()); ptiUser = HeapAlloc(GetProcessHeap(), 0, cbti); if (GetTokenInformation(hToken, TokenUser, ptiUser, cbti, &cbti)) { acc_sizeA = dom_sizeA = MAX_PATH; ret = LookupAccountSidA(NULL, ptiUser->User.Sid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use); ok(ret, "LookupAccountSidA() Expected TRUE, got FALSE\n"); user_sizeA = MAX_PATH; ret = GetUserNameA(usernameA , &user_sizeA); ok(ret, "GetUserNameA() Expected TRUE, got FALSE\n"); ok(lstrcmpA(usernameA, accountA) == 0, "LookupAccountSidA() Expected account name: %s got: %s\n", usernameA, accountA ); } HeapFree(GetProcessHeap(), 0, ptiUser);
if (pCreateWellKnownSid) { trace("Well Known SIDs:\n"); for (i = 0; i <= 84; i++) { size = SECURITY_MAX_SID_SIZE; if (pCreateWellKnownSid(i, NULL, &max_sid.sid, &size)) { if (ConvertSidToStringSidA(&max_sid.sid, &str_sidA)) { acc_sizeA = MAX_PATH; dom_sizeA = MAX_PATH; if (LookupAccountSidA(NULL, &max_sid.sid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use)) trace(" %d: %s %s\\%s %d\n", i, str_sidA, domainA, accountA, use); LocalFree(str_sidA); } } else { if (GetLastError() != ERROR_INVALID_PARAMETER) trace(" CreateWellKnownSid(%d) failed: %d\n", i, GetLastError()); else trace(" %d: not supported\n", i); } }
pLsaQueryInformationPolicy = (void *)GetProcAddress( hmod, "LsaQueryInformationPolicy"); pLsaOpenPolicy = (void *)GetProcAddress( hmod, "LsaOpenPolicy"); pLsaFreeMemory = (void *)GetProcAddress( hmod, "LsaFreeMemory"); pLsaClose = (void *)GetProcAddress( hmod, "LsaClose");
if (pLsaQueryInformationPolicy && pLsaOpenPolicy && pLsaFreeMemory && pLsaClose) { NTSTATUS status; LSA_HANDLE handle; LSA_OBJECT_ATTRIBUTES object_attributes;
ZeroMemory(&object_attributes, sizeof(object_attributes)); object_attributes.Length = sizeof(object_attributes);
status = pLsaOpenPolicy( NULL, &object_attributes, POLICY_ALL_ACCESS, &handle); ok(status == STATUS_SUCCESS || status == STATUS_ACCESS_DENIED, "LsaOpenPolicy(POLICY_ALL_ACCESS) returned 0x%08x\n", status);
/* try a more restricted access mask if necessary */ if (status == STATUS_ACCESS_DENIED) { trace("LsaOpenPolicy(POLICY_ALL_ACCESS) failed, trying POLICY_VIEW_LOCAL_INFORMATION\n"); status = pLsaOpenPolicy( NULL, &object_attributes, POLICY_VIEW_LOCAL_INFORMATION, &handle); ok(status == STATUS_SUCCESS, "LsaOpenPolicy(POLICY_VIEW_LOCAL_INFORMATION) returned 0x%08x\n", status); }
if (status == STATUS_SUCCESS) { PPOLICY_ACCOUNT_DOMAIN_INFO info; status = pLsaQueryInformationPolicy(handle, PolicyAccountDomainInformation, (PVOID*)&info); ok(status == STATUS_SUCCESS, "LsaQueryInformationPolicy() failed, returned 0x%08x\n", status); if (status == STATUS_SUCCESS) { ok(info->DomainSid!=0, "LsaQueryInformationPolicy(PolicyAccountDomainInformation) missing SID\n"); if (info->DomainSid) { int count = *GetSidSubAuthorityCount(info->DomainSid); CopySid(GetSidLengthRequired(count), &max_sid, info->DomainSid); test_sid_str((PSID)&max_sid.sid); max_sid.sid.SubAuthority[count] = DOMAIN_USER_RID_ADMIN; max_sid.sid.SubAuthorityCount = count + 1; test_sid_str((PSID)&max_sid.sid); max_sid.sid.SubAuthority[count] = DOMAIN_USER_RID_GUEST; test_sid_str((PSID)&max_sid.sid); max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_ADMINS; test_sid_str((PSID)&max_sid.sid); max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_USERS; test_sid_str((PSID)&max_sid.sid); max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_GUESTS; test_sid_str((PSID)&max_sid.sid); max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_COMPUTERS; test_sid_str((PSID)&max_sid.sid); max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_CONTROLLERS; test_sid_str((PSID)&max_sid.sid); max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_CERT_ADMINS; test_sid_str((PSID)&max_sid.sid); max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_SCHEMA_ADMINS; test_sid_str((PSID)&max_sid.sid); max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_ENTERPRISE_ADMINS; test_sid_str((PSID)&max_sid.sid); max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_POLICY_ADMINS; test_sid_str((PSID)&max_sid.sid); max_sid.sid.SubAuthority[count] = DOMAIN_ALIAS_RID_RAS_SERVERS; test_sid_str((PSID)&max_sid.sid); max_sid.sid.SubAuthority[count] = 1000; /* first user account */ test_sid_str((PSID)&max_sid.sid); }
pLsaFreeMemory((LPVOID)info); }
status = pLsaClose(handle); ok(status == STATUS_SUCCESS, "LsaClose() failed, returned 0x%08x\n", status); } } }}
static BOOL get_sid_info(PSID psid, LPSTR *user, LPSTR *dom){ static CHAR account[UNLEN + 1]; static CHAR domain[UNLEN + 1]; DWORD size, dom_size; SID_NAME_USE use;
*user = account; *dom = domain;
size = dom_size = UNLEN + 1; account[0] = '\0'; domain[0] = '\0'; SetLastError(0xdeadbeef); return LookupAccountSidA(NULL, psid, account, &size, domain, &dom_size, &use);}
static void check_wellknown_name(const char* name, WELL_KNOWN_SID_TYPE result){ SID_IDENTIFIER_AUTHORITY ident = { SECURITY_NT_AUTHORITY }; PSID domainsid = NULL; char wk_sid[SECURITY_MAX_SID_SIZE]; DWORD cb;
DWORD sid_size, domain_size; SID_NAME_USE sid_use; LPSTR domain, account, sid_domain, wk_domain, wk_account; PSID psid; BOOL ret ,ret2;
sid_size = 0; domain_size = 0; ret = LookupAccountNameA(NULL, name, NULL, &sid_size, NULL, &domain_size, &sid_use); ok(!ret, " %s Should have failed to lookup account name\n", name); psid = HeapAlloc(GetProcessHeap(),0,sid_size); domain = HeapAlloc(GetProcessHeap(),0,domain_size); ret = LookupAccountNameA(NULL, name, psid, &sid_size, domain, &domain_size, &sid_use);
if (!result) { ok(!ret, " %s Should have failed to lookup account name\n",name); goto cleanup; }
AllocateAndInitializeSid(&ident, 6, SECURITY_NT_NON_UNIQUE, 12, 23, 34, 45, 56, 0, 0, &domainsid); cb = sizeof(wk_sid); if (!pCreateWellKnownSid(result, domainsid, wk_sid, &cb)) { win_skip("SID %i is not available on the system\n",result); goto cleanup; }
ret2 = get_sid_info(wk_sid, &wk_account, &wk_domain); if (!ret2 && GetLastError() == ERROR_NONE_MAPPED) { win_skip("CreateWellKnownSid() succeeded but the account '%s' is not present (W2K)\n", name); goto cleanup; }
get_sid_info(psid, &account, &sid_domain);
ok(ret, "Failed to lookup account name %s\n",name); ok(sid_size != 0, "sid_size was zero\n");
ok(EqualSid(psid,wk_sid),"%s Sid %s fails to match well known sid %s!\n", name, debugstr_sid(psid), debugstr_sid(wk_sid));
ok(!lstrcmpA(account, wk_account), "Expected %s , got %s\n", account, wk_account); ok(!lstrcmpA(domain, wk_domain), "Expected %s, got %s\n", wk_domain, domain); ok(sid_use == SidTypeWellKnownGroup , "Expected Use (5), got %d\n", sid_use);
cleanup: FreeSid(domainsid); HeapFree(GetProcessHeap(),0,psid); HeapFree(GetProcessHeap(),0,domain);}
static void test_LookupAccountName(void){ DWORD sid_size, domain_size, user_size; DWORD sid_save, domain_save; CHAR user_name[UNLEN + 1]; CHAR computer_name[UNLEN + 1]; SID_NAME_USE sid_use; LPSTR domain, account, sid_dom; PSID psid; BOOL ret;
/* native crashes if (assuming all other parameters correct): * - peUse is NULL * - Sid is NULL and cbSid is > 0 * - cbSid or cchReferencedDomainName are NULL * - ReferencedDomainName is NULL and cchReferencedDomainName is the correct size */
user_size = UNLEN + 1; SetLastError(0xdeadbeef); ret = GetUserNameA(user_name, &user_size); ok(ret, "Failed to get user name : %d\n", GetLastError());
/* get sizes */ sid_size = 0; domain_size = 0; sid_use = 0xcafebabe; SetLastError(0xdeadbeef); ret = LookupAccountNameA(NULL, user_name, NULL, &sid_size, NULL, &domain_size, &sid_use); if(!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) { win_skip("LookupAccountNameA is not implemented\n"); return; } ok(!ret, "Expected 0, got %d\n", ret); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); ok(sid_size != 0, "Expected non-zero sid size\n"); ok(domain_size != 0, "Expected non-zero domain size\n"); ok(sid_use == (SID_NAME_USE)0xcafebabe, "Expected 0xcafebabe, got %d\n", sid_use);
sid_save = sid_size; domain_save = domain_size;
psid = HeapAlloc(GetProcessHeap(), 0, sid_size); domain = HeapAlloc(GetProcessHeap(), 0, domain_size);
/* try valid account name */ ret = LookupAccountNameA(NULL, user_name, psid, &sid_size, domain, &domain_size, &sid_use); get_sid_info(psid, &account, &sid_dom); ok(ret, "Failed to lookup account name\n"); ok(sid_size == GetLengthSid(psid), "Expected %d, got %d\n", GetLengthSid(psid), sid_size); ok(!lstrcmpA(account, user_name), "Expected %s, got %s\n", user_name, account); ok(!lstrcmpiA(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain); ok(domain_size == domain_save - 1, "Expected %d, got %d\n", domain_save - 1, domain_size); ok(strlen(domain) == domain_size, "Expected %d, got %d\n", lstrlenA(domain), domain_size); ok(sid_use == SidTypeUser, "Expected SidTypeUser (%d), got %d\n", SidTypeUser, sid_use); domain_size = domain_save; sid_size = sid_save;
if (PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH) { skip("Non-English locale (test with hardcoded 'Everyone')\n"); } else { ret = LookupAccountNameA(NULL, "Everyone", psid, &sid_size, domain, &domain_size, &sid_use); get_sid_info(psid, &account, &sid_dom); ok(ret, "Failed to lookup account name\n"); ok(sid_size != 0, "sid_size was zero\n"); ok(!lstrcmpA(account, "Everyone"), "Expected Everyone, got %s\n", account); ok(!lstrcmpiA(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain); ok(domain_size == 0, "Expected 0, got %d\n", domain_size); ok(strlen(domain) == domain_size, "Expected %d, got %d\n", lstrlenA(domain), domain_size); ok(sid_use == SidTypeWellKnownGroup, "Expected SidTypeWellKnownGroup (%d), got %d\n", SidTypeWellKnownGroup, sid_use); domain_size = domain_save; }
/* NULL Sid with zero sid size */ SetLastError(0xdeadbeef); sid_size = 0; ret = LookupAccountNameA(NULL, user_name, NULL, &sid_size, domain, &domain_size, &sid_use); ok(!ret, "Expected 0, got %d\n", ret); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); ok(sid_size == sid_save, "Expected %d, got %d\n", sid_save, sid_size); ok(domain_size == domain_save, "Expected %d, got %d\n", domain_save, domain_size);
/* try cchReferencedDomainName - 1 */ SetLastError(0xdeadbeef); domain_size--; ret = LookupAccountNameA(NULL, user_name, NULL, &sid_size, domain, &domain_size, &sid_use); ok(!ret, "Expected 0, got %d\n", ret); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); ok(sid_size == sid_save, "Expected %d, got %d\n", sid_save, sid_size); ok(domain_size == domain_save, "Expected %d, got %d\n", domain_save, domain_size);
/* NULL ReferencedDomainName with zero domain name size */ SetLastError(0xdeadbeef); domain_size = 0; ret = LookupAccountNameA(NULL, user_name, psid, &sid_size, NULL, &domain_size, &sid_use); ok(!ret, "Expected 0, got %d\n", ret); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); ok(sid_size == sid_save, "Expected %d, got %d\n", sid_save, sid_size); ok(domain_size == domain_save, "Expected %d, got %d\n", domain_save, domain_size);
HeapFree(GetProcessHeap(), 0, psid); HeapFree(GetProcessHeap(), 0, domain);
/* get sizes for NULL account name */ sid_size = 0; domain_size = 0; sid_use = 0xcafebabe; SetLastError(0xdeadbeef); ret = LookupAccountNameA(NULL, NULL, NULL, &sid_size, NULL, &domain_size, &sid_use); if (!ret && GetLastError() == ERROR_NONE_MAPPED) win_skip("NULL account name doesn't work on NT4\n"); else { ok(!ret, "Expected 0, got %d\n", ret); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); ok(sid_size != 0, "Expected non-zero sid size\n"); ok(domain_size != 0, "Expected non-zero domain size\n"); ok(sid_use == (SID_NAME_USE)0xcafebabe, "Expected 0xcafebabe, got %d\n", sid_use);
psid = HeapAlloc(GetProcessHeap(), 0, sid_size); domain = HeapAlloc(GetProcessHeap(), 0, domain_size);
/* try NULL account name */ ret = LookupAccountNameA(NULL, NULL, psid, &sid_size, domain, &domain_size, &sid_use); get_sid_info(psid, &account, &sid_dom); ok(ret, "Failed to lookup account name\n"); /* Using a fixed string will not work on different locales */ ok(!lstrcmpiA(account, domain), "Got %s for account and %s for domain, these should be the same\n", account, domain); ok(sid_use == SidTypeDomain, "Expected SidTypeDomain (%d), got %d\n", SidTypeDomain, sid_use);
HeapFree(GetProcessHeap(), 0, psid); HeapFree(GetProcessHeap(), 0, domain); }
/* try an invalid account name */ SetLastError(0xdeadbeef); sid_size = 0; domain_size = 0; ret = LookupAccountNameA(NULL, "oogabooga", NULL, &sid_size, NULL, &domain_size, &sid_use); ok(!ret, "Expected 0, got %d\n", ret); ok(GetLastError() == ERROR_NONE_MAPPED || broken(GetLastError() == ERROR_TRUSTED_RELATIONSHIP_FAILURE), "Expected ERROR_NONE_MAPPED, got %d\n", GetLastError()); ok(sid_size == 0, "Expected 0, got %d\n", sid_size); ok(domain_size == 0, "Expected 0, got %d\n", domain_size);
/* try an invalid system name */ SetLastError(0xdeadbeef); sid_size = 0; domain_size = 0; ret = LookupAccountNameA("deepthought", NULL, NULL, &sid_size, NULL, &domain_size, &sid_use); ok(!ret, "Expected 0, got %d\n", ret); ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE || GetLastError() == RPC_S_INVALID_NET_ADDR /* Vista */, "Expected RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR, got %d\n", GetLastError()); ok(sid_size == 0, "Expected 0, got %d\n", sid_size); ok(domain_size == 0, "Expected 0, got %d\n", domain_size);
/* try with the computer name as the account name */ domain_size = sizeof(computer_name); GetComputerNameA(computer_name, &domain_size); sid_size = 0; domain_size = 0; ret = LookupAccountNameA(NULL, computer_name, NULL, &sid_size, NULL, &domain_size, &sid_use); ok(!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER || GetLastError() == ERROR_NONE_MAPPED /* in a domain */ || broken(GetLastError() == ERROR_TRUSTED_DOMAIN_FAILURE) || broken(GetLastError() == ERROR_TRUSTED_RELATIONSHIP_FAILURE)), "LookupAccountNameA failed: %d\n", GetLastError()); if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { psid = HeapAlloc(GetProcessHeap(), 0, sid_size); domain = HeapAlloc(GetProcessHeap(), 0, domain_size); ret = LookupAccountNameA(NULL, computer_name, psid, &sid_size, domain, &domain_size, &sid_use); ok(ret, "LookupAccountNameA failed: %d\n", GetLastError()); ok(sid_use == SidTypeDomain || (sid_use == SidTypeUser && ! strcmp(computer_name, user_name)), "expected SidTypeDomain for %s, got %d\n", computer_name, sid_use); HeapFree(GetProcessHeap(), 0, domain); HeapFree(GetProcessHeap(), 0, psid); }
/* Well Known names */ if (!pCreateWellKnownSid) { win_skip("CreateWellKnownSid not available\n"); return; }
if (PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH) { skip("Non-English locale (skipping well known name creation tests)\n"); return; }
check_wellknown_name("LocalService", WinLocalServiceSid); check_wellknown_name("Local Service", WinLocalServiceSid); /* 2 spaces */ check_wellknown_name("Local Service", 0); check_wellknown_name("NetworkService", WinNetworkServiceSid); check_wellknown_name("Network Service", WinNetworkServiceSid);
/* example of some names where the spaces are not optional */ check_wellknown_name("Terminal Server User", WinTerminalServerSid); check_wellknown_name("TerminalServer User", 0); check_wellknown_name("TerminalServerUser", 0); check_wellknown_name("Terminal ServerUser", 0);
check_wellknown_name("enterprise domain controllers",WinEnterpriseControllersSid); check_wellknown_name("enterprisedomain controllers", 0); check_wellknown_name("enterprise domaincontrollers", 0); check_wellknown_name("enterprisedomaincontrollers", 0);
/* case insensitivity */ check_wellknown_name("lOCAlServICE", WinLocalServiceSid);
/* fully qualified account names */ check_wellknown_name("NT AUTHORITY\\LocalService", WinLocalServiceSid); check_wellknown_name("nt authority\\Network Service", WinNetworkServiceSid); check_wellknown_name("nt authority test\\Network Service", 0); check_wellknown_name("Dummy\\Network Service", 0); check_wellknown_name("ntauthority\\Network Service", 0);}
static void test_security_descriptor(void){ SECURITY_DESCRIPTOR sd, *sd_rel, *sd_rel2, *sd_abs; char buf[8192]; DWORD size, size_dacl, size_sacl, size_owner, size_group; BOOL isDefault, isPresent, ret; PACL pacl, dacl, sacl; PSID psid, owner, group;
SetLastError(0xdeadbeef); ret = InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); if (ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) { win_skip("InitializeSecurityDescriptor is not implemented\n"); return; }
ok(GetSecurityDescriptorOwner(&sd, &psid, &isDefault), "GetSecurityDescriptorOwner failed\n"); expect_eq(psid, NULL, PSID, "%p"); expect_eq(isDefault, FALSE, BOOL, "%d"); sd.Control |= SE_DACL_PRESENT | SE_SACL_PRESENT;
SetLastError(0xdeadbeef); size = 5; expect_eq(MakeSelfRelativeSD(&sd, buf, &size), FALSE, BOOL, "%d"); expect_eq(GetLastError(), ERROR_INSUFFICIENT_BUFFER, DWORD, "%u"); ok(size > 5, "Size not increased\n"); if (size <= 8192) { expect_eq(MakeSelfRelativeSD(&sd, buf, &size), TRUE, BOOL, "%d"); ok(GetSecurityDescriptorOwner(&sd, &psid, &isDefault), "GetSecurityDescriptorOwner failed\n"); expect_eq(psid, NULL, PSID, "%p"); expect_eq(isDefault, FALSE, BOOL, "%d"); ok(GetSecurityDescriptorGroup(&sd, &psid, &isDefault), "GetSecurityDescriptorGroup failed\n"); expect_eq(psid, NULL, PSID, "%p"); expect_eq(isDefault, FALSE, BOOL, "%d"); ok(GetSecurityDescriptorDacl(&sd, &isPresent, &pacl, &isDefault), "GetSecurityDescriptorDacl failed\n"); expect_eq(isPresent, TRUE, BOOL, "%d"); expect_eq(psid, NULL, PSID, "%p"); expect_eq(isDefault, FALSE, BOOL, "%d"); ok(GetSecurityDescriptorSacl(&sd, &isPresent, &pacl, &isDefault), "GetSecurityDescriptorSacl failed\n"); expect_eq(isPresent, TRUE, BOOL, "%d"); expect_eq(psid, NULL, PSID, "%p"); expect_eq(isDefault, FALSE, BOOL, "%d"); }
ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( "O:SYG:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)" "(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)" "(AU;NPSA;0x12019f;;;SU)", SDDL_REVISION_1, (void **)&sd_rel, NULL); ok(ret, "got %u\n", GetLastError());
size = 0; ret = MakeSelfRelativeSD(sd_rel, NULL, &size); todo_wine ok(!ret && GetLastError() == ERROR_BAD_DESCRIPTOR_FORMAT, "got %u\n", GetLastError());
/* convert to absolute form */ size = size_dacl = size_sacl = size_owner = size_group = 0; ret = MakeAbsoluteSD(sd_rel, NULL, &size, NULL, &size_dacl, NULL, &size_sacl, NULL, &size_owner, NULL, &size_group); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %u\n", GetLastError());
sd_abs = HeapAlloc(GetProcessHeap(), 0, size + size_dacl + size_sacl + size_owner + size_group); dacl = (PACL)(sd_abs + 1); sacl = (PACL)((char *)dacl + size_dacl); owner = (PSID)((char *)sacl + size_sacl); group = (PSID)((char *)owner + size_owner); ret = MakeAbsoluteSD(sd_rel, sd_abs, &size, dacl, &size_dacl, sacl, &size_sacl, owner, &size_owner, group, &size_group); ok(ret, "got %u\n", GetLastError());
size = 0; ret = MakeSelfRelativeSD(sd_abs, NULL, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %u\n", GetLastError()); ok(size == 184, "got %u\n", size);
size += 4; sd_rel2 = HeapAlloc(GetProcessHeap(), 0, size); ret = MakeSelfRelativeSD(sd_abs, sd_rel2, &size); ok(ret, "got %u\n", GetLastError()); ok(size == 188, "got %u\n", size);
HeapFree(GetProcessHeap(), 0, sd_abs); HeapFree(GetProcessHeap(), 0, sd_rel2); LocalFree(sd_rel);}
#define TEST_GRANTED_ACCESS(a,b) test_granted_access(a,b,0,__LINE__)#define TEST_GRANTED_ACCESS2(a,b,c) test_granted_access(a,b,c,__LINE__)static void test_granted_access(HANDLE handle, ACCESS_MASK access, ACCESS_MASK alt, int line){ OBJECT_BASIC_INFORMATION obj_info; NTSTATUS status;
if (!pNtQueryObject) { skip_(__FILE__, line)("Not NT platform - skipping tests\n"); return; }
status = pNtQueryObject( handle, ObjectBasicInformation, &obj_info, sizeof(obj_info), NULL ); ok_(__FILE__, line)(!status, "NtQueryObject with err: %08x\n", status); if (alt) ok_(__FILE__, line)(obj_info.GrantedAccess == access || obj_info.GrantedAccess == alt, "Granted access should be 0x%08x " "or 0x%08x, instead of 0x%08x\n", access, alt, obj_info.GrantedAccess); else ok_(__FILE__, line)(obj_info.GrantedAccess == access, "Granted access should " "be 0x%08x, instead of 0x%08x\n", access, obj_info.GrantedAccess);}
#define CHECK_SET_SECURITY(o,i,e) \ do{ \ BOOL res_; \ DWORD err; \ SetLastError( 0xdeadbeef ); \ res_ = SetKernelObjectSecurity( o, i, SecurityDescriptor ); \ err = GetLastError(); \ if (e == ERROR_SUCCESS) \ ok(res_, "SetKernelObjectSecurity failed with %d\n", err); \ else \ ok(!res_ && err == e, "SetKernelObjectSecurity should have failed " \ "with %s, instead of %d\n", #e, err); \ }while(0)
static void test_process_security(void){ BOOL res; PTOKEN_USER user; PTOKEN_OWNER owner; PTOKEN_PRIMARY_GROUP group; PSID AdminSid = NULL, UsersSid = NULL, UserSid = NULL; PACL Acl = NULL, ThreadAcl = NULL; SECURITY_DESCRIPTOR *SecurityDescriptor = NULL, *ThreadSecurityDescriptor = NULL; char buffer[MAX_PATH], account[MAX_PATH], domain[MAX_PATH]; PROCESS_INFORMATION info; STARTUPINFOA startup; SECURITY_ATTRIBUTES psa, tsa; HANDLE token, event; DWORD size, acc_size, dom_size, ret; SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY }; PSID EveryoneSid = NULL; SID_NAME_USE use;
Acl = HeapAlloc(GetProcessHeap(), 0, 256); res = InitializeAcl(Acl, 256, ACL_REVISION); if (!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) { win_skip("ACLs not implemented - skipping tests\n"); HeapFree(GetProcessHeap(), 0, Acl); return; } ok(res, "InitializeAcl failed with error %d\n", GetLastError());
res = AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid); ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
/* get owner from the token we might be running as a user not admin */ res = OpenProcessToken( GetCurrentProcess(), MAXIMUM_ALLOWED, &token ); ok(res, "OpenProcessToken failed with error %d\n", GetLastError()); if (!res) { HeapFree(GetProcessHeap(), 0, Acl); return; }
res = GetTokenInformation( token, TokenOwner, NULL, 0, &size ); ok(!res, "Expected failure, got %d\n", res); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
owner = HeapAlloc(GetProcessHeap(), 0, size); res = GetTokenInformation( token, TokenOwner, owner, size, &size ); ok(res, "GetTokenInformation failed with error %d\n", GetLastError()); AdminSid = owner->Owner; test_sid_str(AdminSid);
res = GetTokenInformation( token, TokenPrimaryGroup, NULL, 0, &size ); ok(!res, "Expected failure, got %d\n", res); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
group = HeapAlloc(GetProcessHeap(), 0, size); res = GetTokenInformation( token, TokenPrimaryGroup, group, size, &size ); ok(res, "GetTokenInformation failed with error %d\n", GetLastError()); UsersSid = group->PrimaryGroup; test_sid_str(UsersSid);
acc_size = sizeof(account); dom_size = sizeof(domain); ret = LookupAccountSidA( NULL, UsersSid, account, &acc_size, domain, &dom_size, &use ); ok(ret, "LookupAccountSid failed with %d\n", ret); ok(use == SidTypeGroup, "expect SidTypeGroup, got %d\n", use); ok(!strcmp(account, "None"), "expect None, got %s\n", account);
res = GetTokenInformation( token, TokenUser, NULL, 0, &size ); ok(!res, "Expected failure, got %d\n", res); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
user = HeapAlloc(GetProcessHeap(), 0, size); res = GetTokenInformation( token, TokenUser, user, size, &size ); ok(res, "GetTokenInformation failed with error %d\n", GetLastError()); UserSid = user->User.Sid; test_sid_str(UserSid); ok(EqualPrefixSid(UsersSid, UserSid), "TokenPrimaryGroup Sid and TokenUser Sid don't match.\n");
CloseHandle( token ); if (!res) { HeapFree(GetProcessHeap(), 0, group); HeapFree(GetProcessHeap(), 0, owner); HeapFree(GetProcessHeap(), 0, user); HeapFree(GetProcessHeap(), 0, Acl); return; }
res = AddAccessDeniedAce(Acl, ACL_REVISION, PROCESS_VM_READ, AdminSid); ok(res, "AddAccessDeniedAce failed with error %d\n", GetLastError()); res = AddAccessAllowedAce(Acl, ACL_REVISION, PROCESS_ALL_ACCESS, AdminSid); ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
SecurityDescriptor = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH); res = InitializeSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION); ok(res, "InitializeSecurityDescriptor failed with error %d\n", GetLastError());
event = CreateEventA( NULL, TRUE, TRUE, "test_event" ); ok(event != NULL, "CreateEvent %d\n", GetLastError());
SecurityDescriptor->Revision = 0; CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_UNKNOWN_REVISION ); SecurityDescriptor->Revision = SECURITY_DESCRIPTOR_REVISION;
CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_INVALID_SECURITY_DESCR ); CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_INVALID_SECURITY_DESCR ); CHECK_SET_SECURITY( event, SACL_SECURITY_INFORMATION, ERROR_ACCESS_DENIED ); CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS ); /* NULL DACL is valid and means that everyone has access */ SecurityDescriptor->Control |= SE_DACL_PRESENT; CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
/* Set owner and group and dacl */ res = SetSecurityDescriptorOwner(SecurityDescriptor, AdminSid, FALSE); ok(res, "SetSecurityDescriptorOwner failed with error %d\n", GetLastError()); CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_SUCCESS ); test_owner_equal( event, AdminSid, __LINE__ );
res = SetSecurityDescriptorGroup(SecurityDescriptor, EveryoneSid, FALSE); ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError()); CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_SUCCESS ); test_group_equal( event, EveryoneSid, __LINE__ );
res = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE); ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError()); CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS ); /* setting a dacl should not change the owner or group */ test_owner_equal( event, AdminSid, __LINE__ ); test_group_equal( event, EveryoneSid, __LINE__ );
/* Test again with a different SID in case the previous SID also happens to * be the one that is incorrectly replacing the group. */ res = SetSecurityDescriptorGroup(SecurityDescriptor, UsersSid, FALSE); ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError()); CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_SUCCESS ); test_group_equal( event, UsersSid, __LINE__ );
res = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE); ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError()); CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS ); test_group_equal( event, UsersSid, __LINE__ );
sprintf(buffer, "%s tests/security.c test", myARGV[0]); memset(&startup, 0, sizeof(startup)); startup.cb = sizeof(startup); startup.dwFlags = STARTF_USESHOWWINDOW; startup.wShowWindow = SW_SHOWNORMAL;
psa.nLength = sizeof(psa); psa.lpSecurityDescriptor = SecurityDescriptor; psa.bInheritHandle = TRUE;
ThreadSecurityDescriptor = HeapAlloc( GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH ); res = InitializeSecurityDescriptor( ThreadSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION ); ok(res, "InitializeSecurityDescriptor failed with error %d\n", GetLastError());
ThreadAcl = HeapAlloc( GetProcessHeap(), 0, 256 ); res = InitializeAcl( ThreadAcl, 256, ACL_REVISION ); ok(res, "InitializeAcl failed with error %d\n", GetLastError()); res = AddAccessDeniedAce( ThreadAcl, ACL_REVISION, THREAD_SET_THREAD_TOKEN, AdminSid ); ok(res, "AddAccessDeniedAce failed with error %d\n", GetLastError() ); res = AddAccessAllowedAce( ThreadAcl, ACL_REVISION, THREAD_ALL_ACCESS, AdminSid ); ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
res = SetSecurityDescriptorOwner( ThreadSecurityDescriptor, AdminSid, FALSE ); ok(res, "SetSecurityDescriptorOwner failed with error %d\n", GetLastError()); res = SetSecurityDescriptorGroup( ThreadSecurityDescriptor, UsersSid, FALSE ); ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError()); res = SetSecurityDescriptorDacl( ThreadSecurityDescriptor, TRUE, ThreadAcl, FALSE ); ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
tsa.nLength = sizeof(tsa); tsa.lpSecurityDescriptor = ThreadSecurityDescriptor; tsa.bInheritHandle = TRUE;
/* Doesn't matter what ACL say we should get full access for ourselves */ res = CreateProcessA( NULL, buffer, &psa, &tsa, FALSE, 0, NULL, NULL, &startup, &info ); ok(res, "CreateProcess with err:%d\n", GetLastError()); TEST_GRANTED_ACCESS2( info.hProcess, PROCESS_ALL_ACCESS_NT4, STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL ); TEST_GRANTED_ACCESS2( info.hThread, THREAD_ALL_ACCESS_NT4, STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL ); winetest_wait_child_process( info.hProcess );
FreeSid(EveryoneSid); CloseHandle( info.hProcess ); CloseHandle( info.hThread ); CloseHandle( event ); HeapFree(GetProcessHeap(), 0, group); HeapFree(GetProcessHeap(), 0, owner); HeapFree(GetProcessHeap(), 0, user); HeapFree(GetProcessHeap(), 0, Acl); HeapFree(GetProcessHeap(), 0, SecurityDescriptor); HeapFree(GetProcessHeap(), 0, ThreadAcl); HeapFree(GetProcessHeap(), 0, ThreadSecurityDescriptor);}
static void test_process_security_child(void){ HANDLE handle, handle1; BOOL ret; DWORD err;
handle = OpenProcess( PROCESS_TERMINATE, FALSE, GetCurrentProcessId() ); ok(handle != NULL, "OpenProcess(PROCESS_TERMINATE) with err:%d\n", GetLastError()); TEST_GRANTED_ACCESS( handle, PROCESS_TERMINATE );
ret = DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(), &handle1, 0, TRUE, DUPLICATE_SAME_ACCESS ); ok(ret, "duplicating handle err:%d\n", GetLastError()); TEST_GRANTED_ACCESS( handle1, PROCESS_TERMINATE );
CloseHandle( handle1 );
SetLastError( 0xdeadbeef ); ret = DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(), &handle1, PROCESS_ALL_ACCESS, TRUE, 0 ); err = GetLastError(); ok(!ret && err == ERROR_ACCESS_DENIED, "duplicating handle should have failed " "with STATUS_ACCESS_DENIED, instead of err:%d\n", err);
CloseHandle( handle );
/* These two should fail - they are denied by ACL */ handle = OpenProcess( PROCESS_VM_READ, FALSE, GetCurrentProcessId() ); ok(handle == NULL, "OpenProcess(PROCESS_VM_READ) should have failed\n"); handle = OpenProcess( PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId() ); ok(handle == NULL, "OpenProcess(PROCESS_ALL_ACCESS) should have failed\n");
/* Documented privilege elevation */ ret = DuplicateHandle( GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(), &handle, 0, TRUE, DUPLICATE_SAME_ACCESS ); ok(ret, "duplicating handle err:%d\n", GetLastError()); TEST_GRANTED_ACCESS2( handle, PROCESS_ALL_ACCESS_NT4, STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL );
CloseHandle( handle );
/* Same only explicitly asking for all access rights */ ret = DuplicateHandle( GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(), &handle, PROCESS_ALL_ACCESS, TRUE, 0 ); ok(ret, "duplicating handle err:%d\n", GetLastError()); TEST_GRANTED_ACCESS2( handle, PROCESS_ALL_ACCESS_NT4, PROCESS_ALL_ACCESS | PROCESS_QUERY_LIMITED_INFORMATION ); ret = DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(), &handle1, PROCESS_VM_READ, TRUE, 0 ); ok(ret, "duplicating handle err:%d\n", GetLastError()); TEST_GRANTED_ACCESS( handle1, PROCESS_VM_READ ); CloseHandle( handle1 ); CloseHandle( handle );
/* Test thread security */ handle = OpenThread( THREAD_TERMINATE, FALSE, GetCurrentThreadId() ); ok(handle != NULL, "OpenThread(THREAD_TERMINATE) with err:%d\n", GetLastError()); TEST_GRANTED_ACCESS( handle, PROCESS_TERMINATE ); CloseHandle( handle );
handle = OpenThread( THREAD_SET_THREAD_TOKEN, FALSE, GetCurrentThreadId() ); ok(handle == NULL, "OpenThread(THREAD_SET_THREAD_TOKEN) should have failed\n");}
static void test_impersonation_level(void){ HANDLE Token, ProcessToken; HANDLE Token2; DWORD Size; TOKEN_PRIVILEGES *Privileges; TOKEN_USER *User; PRIVILEGE_SET *PrivilegeSet; BOOL AccessGranted; BOOL ret; HKEY hkey; DWORD error;
if( !pDuplicateTokenEx ) { win_skip("DuplicateTokenEx is not available\n"); return; } SetLastError(0xdeadbeef); ret = ImpersonateSelf(SecurityAnonymous); if(!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) { win_skip("ImpersonateSelf is not implemented\n"); return; } ok(ret, "ImpersonateSelf(SecurityAnonymous) failed with error %d\n", GetLastError()); ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY_SOURCE | TOKEN_IMPERSONATE | TOKEN_ADJUST_DEFAULT, TRUE, &Token); ok(!ret, "OpenThreadToken should have failed\n"); error = GetLastError(); ok(error == ERROR_CANT_OPEN_ANONYMOUS, "OpenThreadToken on anonymous token should have returned ERROR_CANT_OPEN_ANONYMOUS instead of %d\n", error); /* can't perform access check when opening object against an anonymous impersonation token */ todo_wine { error = RegOpenKeyExA(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey); ok(error == ERROR_INVALID_HANDLE || error == ERROR_CANT_OPEN_ANONYMOUS || error == ERROR_BAD_IMPERSONATION_LEVEL, "RegOpenKeyEx failed with %d\n", error); } RevertToSelf();
ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &ProcessToken); ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
ret = pDuplicateTokenEx(ProcessToken, TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE, NULL, SecurityAnonymous, TokenImpersonation, &Token); ok(ret, "DuplicateTokenEx failed with error %d\n", GetLastError()); /* can't increase the impersonation level */ ret = DuplicateToken(Token, SecurityIdentification, &Token2); error = GetLastError(); ok(!ret && error == ERROR_BAD_IMPERSONATION_LEVEL, "Duplicating a token and increasing the impersonation level should have failed with ERROR_BAD_IMPERSONATION_LEVEL instead of %d\n", error); /* we can query anything from an anonymous token, including the user */ ret = GetTokenInformation(Token, TokenUser, NULL, 0, &Size); error = GetLastError(); ok(!ret && error == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenUser) should have failed with ERROR_INSUFFICIENT_BUFFER instead of %d\n", error); User = HeapAlloc(GetProcessHeap(), 0, Size); ret = GetTokenInformation(Token, TokenUser, User, Size, &Size); ok(ret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError()); HeapFree(GetProcessHeap(), 0, User);
/* PrivilegeCheck fails with SecurityAnonymous level */ ret = GetTokenInformation(Token, TokenPrivileges, NULL, 0, &Size); error = GetLastError(); ok(!ret && error == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenPrivileges) should have failed with ERROR_INSUFFICIENT_BUFFER instead of %d\n", error); Privileges = HeapAlloc(GetProcessHeap(), 0, Size); ret = GetTokenInformation(Token, TokenPrivileges, Privileges, Size, &Size); ok(ret, "GetTokenInformation(TokenPrivileges) failed with error %d\n", GetLastError());
PrivilegeSet = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(PRIVILEGE_SET, Privilege[Privileges->PrivilegeCount])); PrivilegeSet->PrivilegeCount = Privileges->PrivilegeCount; memcpy(PrivilegeSet->Privilege, Privileges->Privileges, PrivilegeSet->PrivilegeCount * sizeof(PrivilegeSet->Privilege[0])); PrivilegeSet->Control = PRIVILEGE_SET_ALL_NECESSARY; HeapFree(GetProcessHeap(), 0, Privileges);
ret = PrivilegeCheck(Token, PrivilegeSet, &AccessGranted); error = GetLastError(); ok(!ret && error == ERROR_BAD_IMPERSONATION_LEVEL, "PrivilegeCheck for SecurityAnonymous token should have failed with ERROR_BAD_IMPERSONATION_LEVEL instead of %d\n", error);
CloseHandle(Token);
ret = ImpersonateSelf(SecurityIdentification); ok(ret, "ImpersonateSelf(SecurityIdentification) failed with error %d\n", GetLastError()); ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY_SOURCE | TOKEN_IMPERSONATE | TOKEN_ADJUST_DEFAULT, TRUE, &Token); ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
/* can't perform access check when opening object against an identification impersonation token */ error = RegOpenKeyExA(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey); todo_wine { ok(error == ERROR_INVALID_HANDLE || error == ERROR_BAD_IMPERSONATION_LEVEL, "RegOpenKeyEx should have failed with ERROR_INVALID_HANDLE or ERROR_BAD_IMPERSONATION_LEVEL instead of %d\n", error); } ret = PrivilegeCheck(Token, PrivilegeSet, &AccessGranted); ok(ret, "PrivilegeCheck for SecurityIdentification failed with error %d\n", GetLastError()); CloseHandle(Token); RevertToSelf();
ret = ImpersonateSelf(SecurityImpersonation); ok(ret, "ImpersonateSelf(SecurityImpersonation) failed with error %d\n", GetLastError()); ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY_SOURCE | TOKEN_IMPERSONATE | TOKEN_ADJUST_DEFAULT, TRUE, &Token); ok(ret, "OpenThreadToken failed with error %d\n", GetLastError()); error = RegOpenKeyExA(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey); ok(error == ERROR_SUCCESS, "RegOpenKeyEx should have succeeded instead of failing with %d\n", error); RegCloseKey(hkey); ret = PrivilegeCheck(Token, PrivilegeSet, &AccessGranted); ok(ret, "PrivilegeCheck for SecurityImpersonation failed with error %d\n", GetLastError()); RevertToSelf();
CloseHandle(Token); CloseHandle(ProcessToken);
HeapFree(GetProcessHeap(), 0, PrivilegeSet);}
static void test_SetEntriesInAclW(void){ DWORD res; PSID EveryoneSid = NULL, UsersSid = NULL; PACL OldAcl = NULL, NewAcl; SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY }; SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY }; EXPLICIT_ACCESSW ExplicitAccess; static const WCHAR wszEveryone[] = {'E','v','e','r','y','o','n','e',0}; static const WCHAR wszCurrentUser[] = { 'C','U','R','R','E','N','T','_','U','S','E','R','\0'};
if (!pSetEntriesInAclW) { win_skip("SetEntriesInAclW is not available\n"); return; }
NewAcl = (PACL)0xdeadbeef; res = pSetEntriesInAclW(0, NULL, NULL, &NewAcl); if(res == ERROR_CALL_NOT_IMPLEMENTED) { win_skip("SetEntriesInAclW is not implemented\n"); return; } ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res); ok(NewAcl == NULL || broken(NewAcl != NULL), /* NT4 */ "NewAcl=%p, expected NULL\n", NewAcl); LocalFree(NewAcl);
OldAcl = HeapAlloc(GetProcessHeap(), 0, 256); res = InitializeAcl(OldAcl, 256, ACL_REVISION); if(!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) { win_skip("ACLs not implemented - skipping tests\n"); HeapFree(GetProcessHeap(), 0, OldAcl); return; } ok(res, "InitializeAcl failed with error %d\n", GetLastError());
res = AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid); ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
res = AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &UsersSid); ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
res = AddAccessAllowedAce(OldAcl, ACL_REVISION, KEY_READ, UsersSid); ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
ExplicitAccess.grfAccessPermissions = KEY_WRITE; ExplicitAccess.grfAccessMode = GRANT_ACCESS; ExplicitAccess.grfInheritance = NO_INHERITANCE; ExplicitAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID; ExplicitAccess.Trustee.ptstrName = EveryoneSid; ExplicitAccess.Trustee.MultipleTrusteeOperation = 0xDEADBEEF; ExplicitAccess.Trustee.pMultipleTrustee = (PVOID)0xDEADBEEF; res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl); ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res); ok(NewAcl != NULL, "returned acl was NULL\n"); LocalFree(NewAcl);
ExplicitAccess.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; ExplicitAccess.Trustee.pMultipleTrustee = NULL; ExplicitAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl); ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res); ok(NewAcl != NULL, "returned acl was NULL\n"); LocalFree(NewAcl);
if (PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH) { skip("Non-English locale (test with hardcoded 'Everyone')\n"); } else { ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME; ExplicitAccess.Trustee.ptstrName = (LPWSTR)wszEveryone; res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl); ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res); ok(NewAcl != NULL, "returned acl was NULL\n"); LocalFree(NewAcl);
ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_BAD_FORM; res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl); ok(res == ERROR_INVALID_PARAMETER || broken(res == ERROR_NOT_SUPPORTED), /* NT4 */ "SetEntriesInAclW failed: %u\n", res); ok(NewAcl == NULL || broken(NewAcl != NULL), /* NT4 */ "returned acl wasn't NULL: %p\n", NewAcl);
ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME; ExplicitAccess.Trustee.MultipleTrusteeOperation = TRUSTEE_IS_IMPERSONATE; res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl); ok(res == ERROR_INVALID_PARAMETER || broken(res == ERROR_NOT_SUPPORTED), /* NT4 */ "SetEntriesInAclW failed: %u\n", res); ok(NewAcl == NULL || broken(NewAcl != NULL), /* NT4 */ "returned acl wasn't NULL: %p\n", NewAcl);
ExplicitAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; ExplicitAccess.grfAccessMode = SET_ACCESS; res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl); ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res); ok(NewAcl != NULL, "returned acl was NULL\n"); LocalFree(NewAcl); }
ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME; ExplicitAccess.Trustee.ptstrName = (LPWSTR)wszCurrentUser; res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl); ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res); ok(NewAcl != NULL, "returned acl was NULL\n"); LocalFree(NewAcl);
ExplicitAccess.grfAccessMode = REVOKE_ACCESS; ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID; ExplicitAccess.Trustee.ptstrName = UsersSid; res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl); ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res); ok(NewAcl != NULL, "returned acl was NULL\n"); LocalFree(NewAcl);
FreeSid(UsersSid); FreeSid(EveryoneSid); HeapFree(GetProcessHeap(), 0, OldAcl);}
static void test_SetEntriesInAclA(void){ DWORD res; PSID EveryoneSid = NULL, UsersSid = NULL; PACL OldAcl = NULL, NewAcl; SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY }; SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY }; EXPLICIT_ACCESSA ExplicitAccess; static const CHAR szEveryone[] = {'E','v','e','r','y','o','n','e',0}; static const CHAR szCurrentUser[] = { 'C','U','R','R','E','N','T','_','U','S','E','R','\0'};
if (!pSetEntriesInAclA) { win_skip("SetEntriesInAclA is not available\n"); return; }
NewAcl = (PACL)0xdeadbeef; res = pSetEntriesInAclA(0, NULL, NULL, &NewAcl); if(res == ERROR_CALL_NOT_IMPLEMENTED) { win_skip("SetEntriesInAclA is not implemented\n"); return; } ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %u\n", res); ok(NewAcl == NULL || broken(NewAcl != NULL), /* NT4 */ "NewAcl=%p, expected NULL\n", NewAcl); LocalFree(NewAcl);
OldAcl = HeapAlloc(GetProcessHeap(), 0, 256); res = InitializeAcl(OldAcl, 256, ACL_REVISION); if(!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) { win_skip("ACLs not implemented - skipping tests\n"); HeapFree(GetProcessHeap(), 0, OldAcl); return; } ok(res, "InitializeAcl failed with error %d\n", GetLastError());
res = AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid); ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
res = AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &UsersSid); ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
res = AddAccessAllowedAce(OldAcl, ACL_REVISION, KEY_READ, UsersSid); ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
ExplicitAccess.grfAccessPermissions = KEY_WRITE; ExplicitAccess.grfAccessMode = GRANT_ACCESS; ExplicitAccess.grfInheritance = NO_INHERITANCE; ExplicitAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID; ExplicitAccess.Trustee.ptstrName = EveryoneSid; ExplicitAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; ExplicitAccess.Trustee.pMultipleTrustee = NULL; res = pSetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl); ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %u\n", res); ok(NewAcl != NULL, "returned acl was NULL\n"); LocalFree(NewAcl);
ExplicitAccess.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; ExplicitAccess.Trustee.pMultipleTrustee = NULL; ExplicitAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; res = pSetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl); ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %u\n", res); ok(NewAcl != NULL, "returned acl was NULL\n"); LocalFree(NewAcl);
if (PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH) { skip("Non-English locale (test with hardcoded 'Everyone')\n"); } else { ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME; ExplicitAccess.Trustee.ptstrName = (LPSTR)szEveryone; res = pSetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl); ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %u\n", res); ok(NewAcl != NULL, "returned acl was NULL\n"); LocalFree(NewAcl);
ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_BAD_FORM; res = pSetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl); ok(res == ERROR_INVALID_PARAMETER || broken(res == ERROR_NOT_SUPPORTED), /* NT4 */ "SetEntriesInAclA failed: %u\n", res); ok(NewAcl == NULL || broken(NewAcl != NULL), /* NT4 */ "returned acl wasn't NULL: %p\n", NewAcl);
ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME; ExplicitAccess.Trustee.MultipleTrusteeOperation = TRUSTEE_IS_IMPERSONATE; res = pSetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl); ok(res == ERROR_INVALID_PARAMETER || broken(res == ERROR_NOT_SUPPORTED), /* NT4 */ "SetEntriesInAclA failed: %u\n", res); ok(NewAcl == NULL || broken(NewAcl != NULL), /* NT4 */ "returned acl wasn't NULL: %p\n", NewAcl);
ExplicitAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; ExplicitAccess.grfAccessMode = SET_ACCESS; res = pSetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl); ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %u\n", res); ok(NewAcl != NULL, "returned acl was NULL\n"); LocalFree(NewAcl); }
ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME; ExplicitAccess.Trustee.ptstrName = (LPSTR)szCurrentUser; res = pSetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl); ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %u\n", res); ok(NewAcl != NULL, "returned acl was NULL\n"); LocalFree(NewAcl);
ExplicitAccess.grfAccessMode = REVOKE_ACCESS; ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID; ExplicitAccess.Trustee.ptstrName = UsersSid; res = pSetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl); ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %u\n", res); ok(NewAcl != NULL, "returned acl was NULL\n"); LocalFree(NewAcl);
FreeSid(UsersSid); FreeSid(EveryoneSid); HeapFree(GetProcessHeap(), 0, OldAcl);}
/* helper function for test_CreateDirectoryA */static void get_nt_pathW(const char *name, UNICODE_STRING *nameW){ UNICODE_STRING strW; ANSI_STRING str; NTSTATUS status; BOOLEAN ret;
pRtlInitAnsiString(&str, name);
status = pRtlAnsiStringToUnicodeString(&strW, &str, TRUE); ok(!status, "RtlAnsiStringToUnicodeString failed with %08x\n", status);
ret = pRtlDosPathNameToNtPathName_U(strW.Buffer, nameW, NULL, NULL); ok(ret, "RtlDosPathNameToNtPathName_U failed\n");
pRtlFreeUnicodeString(&strW);}
static void test_inherited_dacl(PACL dacl, PSID admin_sid, PSID user_sid, DWORD flags, DWORD mask, BOOL todo_count, BOOL todo_sid, BOOL todo_flags, int line){ ACL_SIZE_INFORMATION acl_size; ACCESS_ALLOWED_ACE *ace; BOOL bret;
bret = pGetAclInformation(dacl, &acl_size, sizeof(acl_size), AclSizeInformation); ok_(__FILE__, line)(bret, "GetAclInformation failed\n");
todo_wine_if (todo_count) ok_(__FILE__, line)(acl_size.AceCount == 2, "GetAclInformation returned unexpected entry count (%d != 2)\n", acl_size.AceCount);
if (acl_size.AceCount > 0) { bret = pGetAce(dacl, 0, (VOID **)&ace); ok_(__FILE__, line)(bret, "Failed to get Current User ACE\n");
bret = EqualSid(&ace->SidStart, user_sid); todo_wine_if (todo_sid) ok_(__FILE__, line)(bret, "Current User ACE (%s) != Current User SID (%s)\n", debugstr_sid(&ace->SidStart), debugstr_sid(user_sid));
todo_wine_if (todo_flags) ok_(__FILE__, line)(((ACE_HEADER *)ace)->AceFlags == flags, "Current User ACE has unexpected flags (0x%x != 0x%x)\n", ((ACE_HEADER *)ace)->AceFlags, flags);
ok_(__FILE__, line)(ace->Mask == mask, "Current User ACE has unexpected mask (0x%x != 0x%x)\n", ace->Mask, mask); } if (acl_size.AceCount > 1) { bret = pGetAce(dacl, 1, (VOID **)&ace); ok_(__FILE__, line)(bret, "Failed to get Administators Group ACE\n");
bret = EqualSid(&ace->SidStart, admin_sid); todo_wine_if (todo_sid) ok_(__FILE__, line)(bret, "Administators Group ACE (%s) != Administators Group SID (%s)\n", debugstr_sid(&ace->SidStart), debugstr_sid(admin_sid));
todo_wine_if (todo_flags) ok_(__FILE__, line)(((ACE_HEADER *)ace)->AceFlags == flags, "Administators Group ACE has unexpected flags (0x%x != 0x%x)\n", ((ACE_HEADER *)ace)->AceFlags, flags);
ok_(__FILE__, line)(ace->Mask == mask, "Administators Group ACE has unexpected mask (0x%x != 0x%x)\n", ace->Mask, mask); }}
static void test_CreateDirectoryA(void){ char admin_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES], *user; DWORD sid_size = sizeof(admin_ptr), user_size; PSID admin_sid = (PSID) admin_ptr, user_sid; char sd[SECURITY_DESCRIPTOR_MIN_LENGTH]; PSECURITY_DESCRIPTOR pSD = &sd; ACL_SIZE_INFORMATION acl_size; UNICODE_STRING tmpfileW; SECURITY_ATTRIBUTES sa; OBJECT_ATTRIBUTES attr; char tmpfile[MAX_PATH]; char tmpdir[MAX_PATH]; HANDLE token, hTemp; IO_STATUS_BLOCK io; struct _SID *owner; BOOL bret = TRUE; NTSTATUS status; DWORD error; PACL pDacl;
if (!pGetSecurityInfo || !pGetNamedSecurityInfoA || !pCreateWellKnownSid) { win_skip("Required functions are not available\n"); return; }
if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token)) { if (GetLastError() != ERROR_NO_TOKEN) bret = FALSE; else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) bret = FALSE; } if (!bret) { win_skip("Failed to get current user token\n"); return; } bret = GetTokenInformation(token, TokenUser, NULL, 0, &user_size); ok(!bret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER), "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError()); user = HeapAlloc(GetProcessHeap(), 0, user_size); bret = GetTokenInformation(token, TokenUser, user, user_size, &user_size); ok(bret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError()); CloseHandle( token ); user_sid = ((TOKEN_USER *)user)->User.Sid;
sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = pSD; sa.bInheritHandle = TRUE; InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION); pCreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, &sid_size); pDacl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 100); bret = InitializeAcl(pDacl, 100, ACL_REVISION); ok(bret, "Failed to initialize ACL.\n"); bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE, GENERIC_ALL, user_sid); ok(bret, "Failed to add Current User to ACL.\n"); bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE, GENERIC_ALL, admin_sid); ok(bret, "Failed to add Administrator Group to ACL.\n"); bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE); ok(bret, "Failed to add ACL to security descriptor.\n");
GetTempPathA(MAX_PATH, tmpdir); lstrcatA(tmpdir, "Please Remove Me"); bret = CreateDirectoryA(tmpdir, &sa); ok(bret == TRUE, "CreateDirectoryA(%s) failed err=%d\n", tmpdir, GetLastError()); HeapFree(GetProcessHeap(), 0, pDacl);
SetLastError(0xdeadbeef); error = pGetNamedSecurityInfoA(tmpdir, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, (PSID*)&owner, NULL, &pDacl, NULL, &pSD); if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) { win_skip("GetNamedSecurityInfoA is not implemented\n"); goto done; } ok(!error, "GetNamedSecurityInfo failed with error %d\n", error); test_inherited_dacl(pDacl, admin_sid, user_sid, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE, 0x1f01ff, FALSE, FALSE, FALSE, __LINE__); LocalFree(pSD);
/* Test inheritance of ACLs in CreateFile without security descriptor */ strcpy(tmpfile, tmpdir); lstrcatA(tmpfile, "/tmpfile");
hTemp = CreateFileA(tmpfile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, NULL); ok(hTemp != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError());
error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, (PSID *)&owner, NULL, &pDacl, NULL, &pSD); ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n"); test_inherited_dacl(pDacl, admin_sid, user_sid, INHERITED_ACE, 0x1f01ff, FALSE, FALSE, FALSE, __LINE__); LocalFree(pSD); CloseHandle(hTemp);
/* Test inheritance of ACLs in CreateFile with security descriptor - * When a security descriptor is set, then inheritance doesn't take effect */ pSD = &sd; InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION); pDacl = HeapAlloc(GetProcessHeap(), 0, sizeof(ACL)); bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION); ok(bret, "Failed to initialize ACL\n"); bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE); ok(bret, "Failed to add ACL to security descriptor\n");
strcpy(tmpfile, tmpdir); lstrcatA(tmpfile, "/tmpfile");
sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = pSD; sa.bInheritHandle = TRUE; hTemp = CreateFileA(tmpfile, GENERIC_WRITE, FILE_SHARE_READ, &sa, CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, NULL); ok(hTemp != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError()); HeapFree(GetProcessHeap(), 0, pDacl);
error = pGetSecurityInfo(hTemp, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, (PSID *)&owner, NULL, &pDacl, NULL, &pSD); ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error); bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation); ok(bret, "GetAclInformation failed\n"); ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n", acl_size.AceCount); LocalFree(pSD);
error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, (PSID *)&owner, NULL, &pDacl, NULL, &pSD); ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error); bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation); ok(bret, "GetAclInformation failed\n"); ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n", acl_size.AceCount); LocalFree(pSD); CloseHandle(hTemp);
/* Test inheritance of ACLs in NtCreateFile without security descriptor */ strcpy(tmpfile, tmpdir); lstrcatA(tmpfile, "/tmpfile"); get_nt_pathW(tmpfile, &tmpfileW);
attr.Length = sizeof(attr); attr.RootDirectory = 0; attr.ObjectName = &tmpfileW; attr.Attributes = OBJ_CASE_INSENSITIVE; attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL;
status = pNtCreateFile(&hTemp, GENERIC_WRITE | DELETE, &attr, &io, NULL, 0, FILE_SHARE_READ, FILE_CREATE, FILE_DELETE_ON_CLOSE, NULL, 0); ok(!status, "NtCreateFile failed with %08x\n", status); pRtlFreeUnicodeString(&tmpfileW);
error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, (PSID *)&owner, NULL, &pDacl, NULL, &pSD); ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n"); test_inherited_dacl(pDacl, admin_sid, user_sid, INHERITED_ACE, 0x1f01ff, FALSE, FALSE, FALSE, __LINE__); LocalFree(pSD); CloseHandle(hTemp);
/* Test inheritance of ACLs in NtCreateFile with security descriptor - * When a security descriptor is set, then inheritance doesn't take effect */ pSD = &sd; InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION); pDacl = HeapAlloc(GetProcessHeap(), 0, sizeof(ACL)); bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION); ok(bret, "Failed to initialize ACL\n"); bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE); ok(bret, "Failed to add ACL to security descriptor\n");
strcpy(tmpfile, tmpdir); lstrcatA(tmpfile, "/tmpfile"); get_nt_pathW(tmpfile, &tmpfileW);
attr.Length = sizeof(attr); attr.RootDirectory = 0; attr.ObjectName = &tmpfileW; attr.Attributes = OBJ_CASE_INSENSITIVE; attr.SecurityDescriptor = pSD; attr.SecurityQualityOfService = NULL;
status = pNtCreateFile(&hTemp, GENERIC_WRITE | DELETE, &attr, &io, NULL, 0, FILE_SHARE_READ, FILE_CREATE, FILE_DELETE_ON_CLOSE, NULL, 0); ok(!status, "NtCreateFile failed with %08x\n", status); pRtlFreeUnicodeString(&tmpfileW); HeapFree(GetProcessHeap(), 0, pDacl);
error = pGetSecurityInfo(hTemp, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, (PSID *)&owner, NULL, &pDacl, NULL, &pSD); ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error); bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation); ok(bret, "GetAclInformation failed\n"); ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n", acl_size.AceCount); LocalFree(pSD);
error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, (PSID *)&owner, NULL, &pDacl, NULL, &pSD); ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error); bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation); ok(bret, "GetAclInformation failed\n"); todo_wine ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n", acl_size.AceCount); LocalFree(pSD); CloseHandle(hTemp);
/* Test inheritance of ACLs in CreateDirectory without security descriptor */ strcpy(tmpfile, tmpdir); lstrcatA(tmpfile, "/tmpdir"); bret = CreateDirectoryA(tmpfile, NULL); ok(bret == TRUE, "CreateDirectoryA failed with error %u\n", GetLastError());
error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, (PSID *)&owner, NULL, &pDacl, NULL, &pSD); ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n"); test_inherited_dacl(pDacl, admin_sid, user_sid, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERITED_ACE, 0x1f01ff, FALSE, FALSE, FALSE, __LINE__); LocalFree(pSD); bret = RemoveDirectoryA(tmpfile); ok(bret == TRUE, "RemoveDirectoryA failed with error %u\n", GetLastError());
/* Test inheritance of ACLs in CreateDirectory with security descriptor */ pSD = &sd; InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION); pDacl = HeapAlloc(GetProcessHeap(), 0, sizeof(ACL)); bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION); ok(bret, "Failed to initialize ACL\n"); bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE); ok(bret, "Failed to add ACL to security desciptor\n");
strcpy(tmpfile, tmpdir); lstrcatA(tmpfile, "/tmpdir1");
sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = pSD; sa.bInheritHandle = TRUE; bret = CreateDirectoryA(tmpfile, &sa); ok(bret == TRUE, "CreateDirectoryA failed with error %u\n", GetLastError()); HeapFree(GetProcessHeap(), 0, pDacl);
error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, (PSID *)&owner, NULL, &pDacl, NULL, &pSD); ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error); bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation); ok(bret, "GetAclInformation failed\n"); todo_wine ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n", acl_size.AceCount); LocalFree(pSD);
SetLastError(0xdeadbeef); bret = RemoveDirectoryA(tmpfile); error = GetLastError(); ok(bret == FALSE, "RemoveDirectoryA unexpected succeeded\n"); ok(error == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %u\n", error);
pSD = &sd; InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION); pDacl = HeapAlloc(GetProcessHeap(), 0, 100); bret = InitializeAcl(pDacl, 100, ACL_REVISION); ok(bret, "Failed to initialize ACL.\n"); bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid); ok(bret, "Failed to add Current User to ACL.\n"); bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE); ok(bret, "Failed to add ACL to security desciptor.\n"); error = pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pDacl, NULL); ok(error == ERROR_SUCCESS, "SetNamedSecurityInfoA failed with error %u\n", error); HeapFree(GetProcessHeap(), 0, pDacl);
bret = RemoveDirectoryA(tmpfile); ok(bret == TRUE, "RemoveDirectoryA failed with error %u\n", GetLastError());
/* Test inheritance of ACLs in NtCreateFile(..., FILE_DIRECTORY_FILE, ...) without security descriptor */ strcpy(tmpfile, tmpdir); lstrcatA(tmpfile, "/tmpdir"); get_nt_pathW(tmpfile, &tmpfileW);
attr.Length = sizeof(attr); attr.RootDirectory = 0; attr.ObjectName = &tmpfileW; attr.Attributes = OBJ_CASE_INSENSITIVE; attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL;
status = pNtCreateFile(&hTemp, GENERIC_READ | DELETE, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_CREATE, FILE_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE, NULL, 0); ok(!status, "NtCreateFile failed with %08x\n", status); RtlFreeUnicodeString(&tmpfileW);
error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, (PSID *)&owner, NULL, &pDacl, NULL, &pSD); ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n"); test_inherited_dacl(pDacl, admin_sid, user_sid, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERITED_ACE, 0x1f01ff, FALSE, FALSE, FALSE, __LINE__); LocalFree(pSD); CloseHandle(hTemp);
/* Test inheritance of ACLs in NtCreateFile(..., FILE_DIRECTORY_FILE, ...) with security descriptor */ pSD = &sd; InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION); pDacl = HeapAlloc(GetProcessHeap(), 0, sizeof(ACL)); bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION); ok(bret, "Failed to initialize ACL\n"); bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE); ok(bret, "Failed to add ACL to security desciptor\n");
strcpy(tmpfile, tmpdir); lstrcatA(tmpfile, "/tmpdir2"); get_nt_pathW(tmpfile, &tmpfileW);
attr.Length = sizeof(attr); attr.RootDirectory = 0; attr.ObjectName = &tmpfileW; attr.Attributes = OBJ_CASE_INSENSITIVE; attr.SecurityDescriptor = pSD; attr.SecurityQualityOfService = NULL;
status = pNtCreateFile(&hTemp, GENERIC_READ | DELETE, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_CREATE, FILE_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE, NULL, 0); ok(!status, "NtCreateFile failed with %08x\n", status); RtlFreeUnicodeString(&tmpfileW); HeapFree(GetProcessHeap(), 0, pDacl);
error = pGetSecurityInfo(hTemp, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, (PSID *)&owner, NULL, &pDacl, NULL, &pSD); ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error); bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation); ok(bret, "GetAclInformation failed\n"); todo_wine ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n", acl_size.AceCount); LocalFree(pSD);
error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, (PSID *)&owner, NULL, &pDacl, NULL, &pSD); ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error); bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation); ok(bret, "GetAclInformation failed\n"); todo_wine ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n", acl_size.AceCount); LocalFree(pSD); CloseHandle(hTemp);
done: HeapFree(GetProcessHeap(), 0, user); bret = RemoveDirectoryA(tmpdir); ok(bret == TRUE, "RemoveDirectoryA should always succeed\n");}
static void test_GetNamedSecurityInfoA(void){ char admin_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES], *user; char system_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES]; char users_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES]; SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY }; PSID admin_sid = (PSID) admin_ptr, users_sid = (PSID) users_ptr; PSID system_sid = (PSID) system_ptr, user_sid, localsys_sid; DWORD sid_size = sizeof(admin_ptr), user_size; char invalid_path[] = "/an invalid file path"; int users_ace_id = -1, admins_ace_id = -1, i; char software_key[] = "MACHINE\\Software"; char sd[SECURITY_DESCRIPTOR_MIN_LENGTH+sizeof(void*)]; SECURITY_DESCRIPTOR_CONTROL control; ACL_SIZE_INFORMATION acl_size; CHAR windows_dir[MAX_PATH]; PSECURITY_DESCRIPTOR pSD; ACCESS_ALLOWED_ACE *ace; BOOL bret = TRUE, isNT4; char tmpfile[MAX_PATH]; DWORD error, revision; BOOL owner_defaulted; BOOL group_defaulted; BOOL dacl_defaulted; HANDLE token, hTemp, h; PSID owner, group; BOOL dacl_present; PACL pDacl; BYTE flags; NTSTATUS status;
if (!pSetNamedSecurityInfoA || !pGetNamedSecurityInfoA || !pCreateWellKnownSid) { win_skip("Required functions are not available\n"); return; }
if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token)) { if (GetLastError() != ERROR_NO_TOKEN) bret = FALSE; else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) bret = FALSE; } if (!bret) { win_skip("Failed to get current user token\n"); return; } bret = GetTokenInformation(token, TokenUser, NULL, 0, &user_size); ok(!bret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER), "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError()); user = HeapAlloc(GetProcessHeap(), 0, user_size); bret = GetTokenInformation(token, TokenUser, user, user_size, &user_size); ok(bret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError()); CloseHandle( token ); user_sid = ((TOKEN_USER *)user)->User.Sid;
bret = GetWindowsDirectoryA(windows_dir, MAX_PATH); ok(bret, "GetWindowsDirectory failed with error %d\n", GetLastError());
SetLastError(0xdeadbeef); error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &pSD); if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) { win_skip("GetNamedSecurityInfoA is not implemented\n"); HeapFree(GetProcessHeap(), 0, user); return; } ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
bret = GetSecurityDescriptorControl(pSD, &control, &revision); ok(bret, "GetSecurityDescriptorControl failed with error %d\n", GetLastError()); ok((control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == (SE_SELF_RELATIVE|SE_DACL_PRESENT) || broken((control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == SE_DACL_PRESENT), /* NT4 */ "control (0x%x) doesn't have (SE_SELF_RELATIVE|SE_DACL_PRESENT) flags set\n", control); ok(revision == SECURITY_DESCRIPTOR_REVISION1, "revision was %d instead of 1\n", revision);
isNT4 = (control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == SE_DACL_PRESENT;
bret = GetSecurityDescriptorOwner(pSD, &owner, &owner_defaulted); ok(bret, "GetSecurityDescriptorOwner failed with error %d\n", GetLastError()); ok(owner != NULL, "owner should not be NULL\n");
bret = GetSecurityDescriptorGroup(pSD, &group, &group_defaulted); ok(bret, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError()); ok(group != NULL, "group should not be NULL\n"); LocalFree(pSD);
/* NULL descriptor tests */ if(isNT4) { win_skip("NT4 does not support GetNamedSecutityInfo with a NULL descriptor\n"); HeapFree(GetProcessHeap(), 0, user); return; }
error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, NULL); ok(error==ERROR_INVALID_PARAMETER, "GetNamedSecurityInfo failed with error %d\n", error);
pDacl = NULL; error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,DACL_SECURITY_INFORMATION, NULL, NULL, &pDacl, NULL, &pSD); ok(!error, "GetNamedSecurityInfo failed with error %d\n", error); ok(pDacl != NULL, "DACL should not be NULL\n"); LocalFree(pSD);
error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,OWNER_SECURITY_INFORMATION, NULL, NULL, &pDacl, NULL, NULL); ok(error==ERROR_INVALID_PARAMETER, "GetNamedSecurityInfo failed with error %d\n", error);
/* Test behavior of SetNamedSecurityInfo with an invalid path */ SetLastError(0xdeadbeef); error = pSetNamedSecurityInfoA(invalid_path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL); ok(error == ERROR_FILE_NOT_FOUND, "Unexpected error returned: 0x%x\n", error); ok(GetLastError() == 0xdeadbeef, "Expected last error to remain unchanged.\n");
/* Create security descriptor information and test that it comes back the same */ pSD = &sd; pDacl = HeapAlloc(GetProcessHeap(), 0, 100); InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION); pCreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, &sid_size); bret = InitializeAcl(pDacl, 100, ACL_REVISION); ok(bret, "Failed to initialize ACL.\n"); bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid); ok(bret, "Failed to add Current User to ACL.\n"); bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, admin_sid); ok(bret, "Failed to add Administrator Group to ACL.\n"); bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE); ok(bret, "Failed to add ACL to security descriptor.\n"); GetTempFileNameA(".", "foo", 0, tmpfile); hTemp = CreateFileA(tmpfile, WRITE_DAC|GENERIC_WRITE, FILE_SHARE_DELETE|FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL); SetLastError(0xdeadbeef); error = pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pDacl, NULL); HeapFree(GetProcessHeap(), 0, pDacl); if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) { win_skip("SetNamedSecurityInfoA is not implemented\n"); HeapFree(GetProcessHeap(), 0, user); CloseHandle(hTemp); return; } ok(!error, "SetNamedSecurityInfoA failed with error %d\n", error); SetLastError(0xdeadbeef); error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pDacl, NULL, &pSD); if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) { win_skip("GetNamedSecurityInfoA is not implemented\n"); HeapFree(GetProcessHeap(), 0, user); CloseHandle(hTemp); return; } ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation); ok(bret, "GetAclInformation failed\n"); if (acl_size.AceCount > 0) { bret = pGetAce(pDacl, 0, (VOID **)&ace); ok(bret, "Failed to get Current User ACE.\n"); bret = EqualSid(&ace->SidStart, user_sid); ok(bret, "Current User ACE (%s) != Current User SID (%s).\n", debugstr_sid(&ace->SidStart), debugstr_sid(user_sid)); ok(((ACE_HEADER *)ace)->AceFlags == 0, "Current User ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags); ok(ace->Mask == 0x1f01ff, "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask); } if (acl_size.AceCount > 1) { bret = pGetAce(pDacl, 1, (VOID **)&ace); ok(bret, "Failed to get Administators Group ACE.\n"); bret = EqualSid(&ace->SidStart, admin_sid); ok(bret || broken(!bret) /* win2k */, "Administators Group ACE (%s) != Administators Group SID (%s).\n", debugstr_sid(&ace->SidStart), debugstr_sid(admin_sid)); ok(((ACE_HEADER *)ace)->AceFlags == 0, "Administators Group ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags); ok(ace->Mask == 0x1f01ff || broken(ace->Mask == GENERIC_ALL) /* win2k */, "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask); } LocalFree(pSD);
/* show that setting empty DACL is not removing all file permissions */ pDacl = HeapAlloc(GetProcessHeap(), 0, sizeof(ACL)); bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION); ok(bret, "Failed to initialize ACL.\n"); error = pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pDacl, NULL); ok(!error, "SetNamedSecurityInfoA failed with error %d\n", error); HeapFree(GetProcessHeap(), 0, pDacl);
error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pDacl, NULL, &pSD); ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation); ok(bret, "GetAclInformation failed\n"); if (acl_size.AceCount > 0) { bret = pGetAce(pDacl, 0, (VOID **)&ace); ok(bret, "Failed to get ACE.\n"); ok(((ACE_HEADER *)ace)->AceFlags & INHERITED_ACE, "ACE has unexpected flags: 0x%x\n", ((ACE_HEADER *)ace)->AceFlags); } LocalFree(pSD);
h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); ok(h != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError()); CloseHandle(h);
/* test setting NULL DACL */ error = pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL); ok(!error, "SetNamedSecurityInfoA failed with error %d\n", error);
error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pDacl, NULL, &pSD); ok(!error, "GetNamedSecurityInfo failed with error %d\n", error); todo_wine ok(!pDacl, "pDacl != NULL\n"); LocalFree(pSD);
h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); ok(h != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError()); CloseHandle(h);
/* NtSetSecurityObject doesn't inherit DACL entries */ pSD = sd+sizeof(void*)-((ULONG_PTR)sd)%sizeof(void*); InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION); pDacl = HeapAlloc(GetProcessHeap(), 0, 100); bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION); ok(bret, "Failed to initialize ACL.\n"); bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE); ok(bret, "Failed to add ACL to security descriptor.\n"); status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD); ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %x\n", status);
h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); ok(h == INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError()); CloseHandle(h);
pSetSecurityDescriptorControl(pSD, SE_DACL_AUTO_INHERIT_REQ, SE_DACL_AUTO_INHERIT_REQ); status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD); ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %x\n", status);
h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); ok(h == INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError()); CloseHandle(h);
pSetSecurityDescriptorControl(pSD, SE_DACL_AUTO_INHERIT_REQ|SE_DACL_AUTO_INHERITED, SE_DACL_AUTO_INHERIT_REQ|SE_DACL_AUTO_INHERITED); status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD); ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %x\n", status);
h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); ok(h == INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError()); CloseHandle(h);
/* test if DACL is properly mapped to permission */ bret = InitializeAcl(pDacl, 100, ACL_REVISION); ok(bret, "Failed to initialize ACL.\n"); bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid); ok(bret, "Failed to add Current User to ACL.\n"); bret = pAddAccessDeniedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid); ok(bret, "Failed to add Current User to ACL.\n"); bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE); ok(bret, "Failed to add ACL to security descriptor.\n"); status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD); ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %x\n", status);
h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); ok(h != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError()); CloseHandle(h);
bret = InitializeAcl(pDacl, 100, ACL_REVISION); ok(bret, "Failed to initialize ACL.\n"); bret = pAddAccessDeniedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid); ok(bret, "Failed to add Current User to ACL.\n"); bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid); ok(bret, "Failed to add Current User to ACL.\n"); bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE); ok(bret, "Failed to add ACL to security descriptor.\n"); status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD); ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %x\n", status);
h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); ok(h == INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError()); HeapFree(GetProcessHeap(), 0, pDacl); HeapFree(GetProcessHeap(), 0, user); CloseHandle(hTemp);
/* Test querying the ownership of a built-in registry key */ sid_size = sizeof(system_ptr); pCreateWellKnownSid(WinLocalSystemSid, NULL, system_sid, &sid_size); error = pGetNamedSecurityInfoA(software_key, SE_REGISTRY_KEY, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &pSD); ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
bret = AllocateAndInitializeSid(&SIDAuthNT, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &localsys_sid); ok(bret, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
bret = GetSecurityDescriptorOwner(pSD, &owner, &owner_defaulted); ok(bret, "GetSecurityDescriptorOwner failed with error %d\n", GetLastError()); ok(owner != NULL, "owner should not be NULL\n"); ok(EqualSid(owner, admin_sid) || EqualSid(owner, localsys_sid), "MACHINE\\Software owner SID (%s) != Administrators SID (%s) or Local System Sid (%s).\n", debugstr_sid(owner), debugstr_sid(admin_sid), debugstr_sid(localsys_sid));
bret = GetSecurityDescriptorGroup(pSD, &group, &group_defaulted); ok(bret, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError()); ok(group != NULL, "group should not be NULL\n"); ok(EqualSid(group, admin_sid) || broken(EqualSid(group, system_sid)) /* before Win7 */ || broken(((SID*)group)->SubAuthority[0] == SECURITY_NT_NON_UNIQUE) /* Vista */, "MACHINE\\Software group SID (%s) != Local System SID (%s or %s)\n", debugstr_sid(group), debugstr_sid(admin_sid), debugstr_sid(system_sid)); LocalFree(pSD);
/* Test querying the DACL of a built-in registry key */ sid_size = sizeof(users_ptr); pCreateWellKnownSid(WinBuiltinUsersSid, NULL, users_sid, &sid_size); error = pGetNamedSecurityInfoA(software_key, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &pSD); ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
bret = GetSecurityDescriptorDacl(pSD, &dacl_present, &pDacl, &dacl_defaulted); ok(bret, "GetSecurityDescriptorDacl failed with error %d\n", GetLastError()); ok(dacl_present, "DACL should be present\n"); ok(pDacl && IsValidAcl(pDacl), "GetSecurityDescriptorDacl returned invalid DACL.\n"); bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation); ok(bret, "GetAclInformation failed\n"); ok(acl_size.AceCount != 0, "GetAclInformation returned no ACLs\n"); for (i=0; i<acl_size.AceCount; i++) { bret = pGetAce(pDacl, i, (VOID **)&ace); ok(bret, "Failed to get ACE %d.\n", i); bret = EqualSid(&ace->SidStart, users_sid); if (bret) users_ace_id = i; bret = EqualSid(&ace->SidStart, admin_sid); if (bret) admins_ace_id = i; } ok(users_ace_id != -1 || broken(users_ace_id == -1) /* win2k */, "Builtin Users ACE not found.\n"); if (users_ace_id != -1) { bret = pGetAce(pDacl, users_ace_id, (VOID **)&ace); ok(bret, "Failed to get Builtin Users ACE.\n"); flags = ((ACE_HEADER *)ace)->AceFlags; ok(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE) || broken(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE|INHERITED_ACE)) /* w2k8 */ || broken(flags == (CONTAINER_INHERIT_ACE|INHERITED_ACE)) /* win 10 wow64 */ || broken(flags == CONTAINER_INHERIT_ACE), /* win 10 */ "Builtin Users ACE has unexpected flags (0x%x != 0x%x)\n", flags, INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE); ok(ace->Mask == GENERIC_READ || broken(ace->Mask == KEY_READ), /* win 10 */ "Builtin Users ACE has unexpected mask (0x%x != 0x%x)\n", ace->Mask, GENERIC_READ); } ok(admins_ace_id != -1, "Builtin Admins ACE not found.\n"); if (admins_ace_id != -1) { bret = pGetAce(pDacl, admins_ace_id, (VOID **)&ace); ok(bret, "Failed to get Builtin Admins ACE.\n"); flags = ((ACE_HEADER *)ace)->AceFlags; ok(flags == 0x0 || broken(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE|INHERITED_ACE)) /* w2k8 */ || broken(flags == (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)) /* win7 */ || broken(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE)) /* win8+ */ || broken(flags == (CONTAINER_INHERIT_ACE|INHERITED_ACE)) /* win 10 wow64 */ || broken(flags == CONTAINER_INHERIT_ACE), /* win 10 */ "Builtin Admins ACE has unexpected flags (0x%x != 0x0)\n", flags); ok(ace->Mask == KEY_ALL_ACCESS || broken(ace->Mask == GENERIC_ALL) /* w2k8 */, "Builtin Admins ACE has unexpected mask (0x%x != 0x%x)\n", ace->Mask, KEY_ALL_ACCESS); }
FreeSid(localsys_sid); LocalFree(pSD);}
static void test_ConvertStringSecurityDescriptor(void){ BOOL ret; PSECURITY_DESCRIPTOR pSD; static const WCHAR Blank[] = { 0 }; unsigned int i; ULONG size; ACL *acl; static const struct { const char *sidstring; DWORD revision; BOOL ret; DWORD GLE; DWORD altGLE; } cssd[] = { { "D:(A;;GA;;;WD)", 0xdeadbeef, FALSE, ERROR_UNKNOWN_REVISION }, /* test ACE string type */ { "D:(A;;GA;;;WD)", SDDL_REVISION_1, TRUE }, { "D:(D;;GA;;;WD)", SDDL_REVISION_1, TRUE }, { "ERROR:(D;;GA;;;WD)", SDDL_REVISION_1, FALSE, ERROR_INVALID_PARAMETER }, /* test ACE string with spaces */ { " D:(D;;GA;;;WD)", SDDL_REVISION_1, TRUE }, { "D: (D;;GA;;;WD)", SDDL_REVISION_1, TRUE }, { "D:( D;;GA;;;WD)", SDDL_REVISION_1, TRUE }, { "D:(D ;;GA;;;WD)", SDDL_REVISION_1, FALSE, RPC_S_INVALID_STRING_UUID, ERROR_INVALID_ACL }, /* Vista+ */ { "D:(D; ;GA;;;WD)", SDDL_REVISION_1, TRUE }, { "D:(D;; GA;;;WD)", SDDL_REVISION_1, TRUE }, { "D:(D;;GA ;;;WD)", SDDL_REVISION_1, FALSE, ERROR_INVALID_ACL }, { "D:(D;;GA; ;;WD)", SDDL_REVISION_1, TRUE }, { "D:(D;;GA;; ;WD)", SDDL_REVISION_1, TRUE }, { "D:(D;;GA;;; WD)", SDDL_REVISION_1, TRUE }, { "D:(D;;GA;;;WD )", SDDL_REVISION_1, TRUE }, /* test ACE string access rights */ { "D:(A;;GA;;;WD)", SDDL_REVISION_1, TRUE }, { "D:(A;;GRGWGX;;;WD)", SDDL_REVISION_1, TRUE }, { "D:(A;;RCSDWDWO;;;WD)", SDDL_REVISION_1, TRUE }, { "D:(A;;RPWPCCDCLCSWLODTCR;;;WD)", SDDL_REVISION_1, TRUE }, { "D:(A;;FAFRFWFX;;;WD)", SDDL_REVISION_1, TRUE }, { "D:(A;;KAKRKWKX;;;WD)", SDDL_REVISION_1, TRUE }, { "D:(A;;0xFFFFFFFF;;;WD)", SDDL_REVISION_1, TRUE }, { "S:(AU;;0xFFFFFFFF;;;WD)", SDDL_REVISION_1, TRUE }, /* test ACE string access right error case */ { "D:(A;;ROB;;;WD)", SDDL_REVISION_1, FALSE, ERROR_INVALID_ACL }, /* test behaviour with empty strings */ { "", SDDL_REVISION_1, TRUE }, /* test ACE string SID */ { "D:(D;;GA;;;S-1-0-0)", SDDL_REVISION_1, TRUE }, { "D:(D;;GA;;;Nonexistent account)", SDDL_REVISION_1, FALSE, ERROR_INVALID_ACL, ERROR_INVALID_SID } /* W2K */ };
if (!pConvertStringSecurityDescriptorToSecurityDescriptorA) { win_skip("ConvertStringSecurityDescriptorToSecurityDescriptor is not available\n"); return; }
for (i = 0; i < sizeof(cssd)/sizeof(cssd[0]); i++) { DWORD GLE;
SetLastError(0xdeadbeef); ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( cssd[i].sidstring, cssd[i].revision, &pSD, NULL); GLE = GetLastError(); ok(ret == cssd[i].ret, "(%02u) Expected %s (%d)\n", i, cssd[i].ret ? "success" : "failure", GLE); if (!cssd[i].ret) ok(GLE == cssd[i].GLE || (cssd[i].altGLE && GLE == cssd[i].altGLE), "(%02u) Unexpected last error %d\n", i, GLE); if (ret) LocalFree(pSD); }
/* test behaviour with NULL parameters */ SetLastError(0xdeadbeef); ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( NULL, 0xdeadbeef, &pSD, NULL); todo_wine ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GetLastError());
SetLastError(0xdeadbeef); ret = pConvertStringSecurityDescriptorToSecurityDescriptorW( NULL, 0xdeadbeef, &pSD, NULL); ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GetLastError());
SetLastError(0xdeadbeef); ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( "D:(A;;ROB;;;WD)", 0xdeadbeef, NULL, NULL); ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GetLastError());
SetLastError(0xdeadbeef); ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( "D:(A;;ROB;;;WD)", SDDL_REVISION_1, NULL, NULL); ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GetLastError());
/* test behaviour with empty strings */ SetLastError(0xdeadbeef); ret = pConvertStringSecurityDescriptorToSecurityDescriptorW( Blank, SDDL_REVISION_1, &pSD, NULL); ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError()); LocalFree(pSD);
SetLastError(0xdeadbeef); ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( "D:P(A;;GRGW;;;BA)(A;;GRGW;;;S-1-5-21-0-0-0-1000)S:(ML;;NWNR;;;S-1-16-12288)", SDDL_REVISION_1, &pSD, NULL); ok(ret || broken(!ret && GetLastError() == ERROR_INVALID_DATATYPE) /* win2k */, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %u\n", GetLastError()); if (ret) LocalFree(pSD);
/* empty DACL */ size = 0; SetLastError(0xdeadbeef); ret = pConvertStringSecurityDescriptorToSecurityDescriptorA("D:", SDDL_REVISION_1, &pSD, &size); ok(ret, "unexpected error %u\n", GetLastError()); ok(size == sizeof(SECURITY_DESCRIPTOR_RELATIVE) + sizeof(ACL), "got %u\n", size); acl = (ACL *)((char *)pSD + sizeof(SECURITY_DESCRIPTOR_RELATIVE)); ok(acl->AclRevision == ACL_REVISION, "got %u\n", acl->AclRevision); ok(!acl->Sbz1, "got %u\n", acl->Sbz1); ok(acl->AclSize == sizeof(*acl), "got %u\n", acl->AclSize); ok(!acl->AceCount, "got %u\n", acl->AceCount); ok(!acl->Sbz2, "got %u\n", acl->Sbz2); LocalFree(pSD);
/* empty SACL */ size = 0; SetLastError(0xdeadbeef); ret = pConvertStringSecurityDescriptorToSecurityDescriptorA("S:", SDDL_REVISION_1, &pSD, &size); ok(ret, "unexpected error %u\n", GetLastError()); ok(size == sizeof(SECURITY_DESCRIPTOR_RELATIVE) + sizeof(ACL), "got %u\n", size); acl = (ACL *)((char *)pSD + sizeof(SECURITY_DESCRIPTOR_RELATIVE)); ok(!acl->Sbz1, "got %u\n", acl->Sbz1); ok(acl->AclSize == sizeof(*acl), "got %u\n", acl->AclSize); ok(!acl->AceCount, "got %u\n", acl->AceCount); ok(!acl->Sbz2, "got %u\n", acl->Sbz2); LocalFree(pSD);}
static void test_ConvertSecurityDescriptorToString(void){ SECURITY_DESCRIPTOR desc; SECURITY_INFORMATION sec_info = OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION; LPSTR string; DWORD size; PSID psid, psid2; PACL pacl; char sid_buf[256]; char acl_buf[8192]; ULONG len;
if (!pConvertSecurityDescriptorToStringSecurityDescriptorA) { win_skip("ConvertSecurityDescriptorToStringSecurityDescriptor is not available\n"); return; } if (!pCreateWellKnownSid) { win_skip("CreateWellKnownSid is not available\n"); return; }
/* It seems Windows XP adds an extra character to the length of the string for each ACE in an ACL. We * don't replicate this feature so we only test len >= strlen+1. */#define CHECK_RESULT_AND_FREE(exp_str) \ ok(strcmp(string, (exp_str)) == 0, "String mismatch (expected \"%s\", got \"%s\")\n", (exp_str), string); \ ok(len >= (strlen(exp_str) + 1), "Length mismatch (expected %d, got %d)\n", lstrlenA(exp_str) + 1, len); \ LocalFree(string);
#define CHECK_ONE_OF_AND_FREE(exp_str1, exp_str2) \ ok(strcmp(string, (exp_str1)) == 0 || strcmp(string, (exp_str2)) == 0, "String mismatch (expected\n\"%s\" or\n\"%s\", got\n\"%s\")\n", (exp_str1), (exp_str2), string); \ ok(len >= (strlen(exp_str1) + 1) || len >= (strlen(exp_str2) + 1), "Length mismatch (expected %d or %d, got %d)\n", lstrlenA(exp_str1) + 1, lstrlenA(exp_str2) + 1, len); \ LocalFree(string);
InitializeSecurityDescriptor(&desc, SECURITY_DESCRIPTOR_REVISION); ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n"); CHECK_RESULT_AND_FREE("");
size = 4096; pCreateWellKnownSid(WinLocalSid, NULL, sid_buf, &size); SetSecurityDescriptorOwner(&desc, sid_buf, FALSE); ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n"); CHECK_RESULT_AND_FREE("O:S-1-2-0");
SetSecurityDescriptorOwner(&desc, sid_buf, TRUE); ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n"); CHECK_RESULT_AND_FREE("O:S-1-2-0");
size = sizeof(sid_buf); pCreateWellKnownSid(WinLocalSystemSid, NULL, sid_buf, &size); SetSecurityDescriptorOwner(&desc, sid_buf, TRUE); ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n"); CHECK_RESULT_AND_FREE("O:SY");
pConvertStringSidToSidA("S-1-5-21-93476-23408-4576", &psid); SetSecurityDescriptorGroup(&desc, psid, TRUE); ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n"); CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576");
ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, GROUP_SECURITY_INFORMATION, &string, &len), "Conversion failed\n"); CHECK_RESULT_AND_FREE("G:S-1-5-21-93476-23408-4576");
pacl = (PACL)acl_buf; InitializeAcl(pacl, sizeof(acl_buf), ACL_REVISION); SetSecurityDescriptorDacl(&desc, TRUE, pacl, TRUE); ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n"); CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:");
SetSecurityDescriptorDacl(&desc, TRUE, pacl, FALSE); ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n"); CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:");
pConvertStringSidToSidA("S-1-5-6", &psid2); pAddAccessAllowedAceEx(pacl, ACL_REVISION, NO_PROPAGATE_INHERIT_ACE, 0xf0000000, psid2); ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n"); CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)");
pAddAccessAllowedAceEx(pacl, ACL_REVISION, INHERIT_ONLY_ACE|INHERITED_ACE, 0x00000003, psid2); ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n"); CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)");
pAddAccessDeniedAceEx(pacl, ACL_REVISION, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE, 0xffffffff, psid); ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n"); CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)");
pacl = (PACL)acl_buf; InitializeAcl(pacl, sizeof(acl_buf), ACL_REVISION); SetSecurityDescriptorSacl(&desc, TRUE, pacl, FALSE); ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n"); CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:S:");
/* fails in win2k */ SetSecurityDescriptorDacl(&desc, TRUE, NULL, FALSE); pAddAuditAccessAceEx(pacl, ACL_REVISION, VALID_INHERIT_FLAGS, KEY_READ|KEY_WRITE, psid2, TRUE, TRUE); if (pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len)) { CHECK_ONE_OF_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)", /* XP */ "O:SYG:S-1-5-21-93476-23408-4576D:NO_ACCESS_CONTROLS:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)" /* Vista */); }
/* fails in win2k */ pAddAuditAccessAceEx(pacl, ACL_REVISION, NO_PROPAGATE_INHERIT_ACE, FILE_GENERIC_READ|FILE_GENERIC_WRITE, psid2, TRUE, FALSE); if (pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len)) { CHECK_ONE_OF_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)", /* XP */ "O:SYG:S-1-5-21-93476-23408-4576D:NO_ACCESS_CONTROLS:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)" /* Vista */); }
LocalFree(psid2); LocalFree(psid);}
static void test_SetSecurityDescriptorControl (PSECURITY_DESCRIPTOR sec){ SECURITY_DESCRIPTOR_CONTROL ref; SECURITY_DESCRIPTOR_CONTROL test;
SECURITY_DESCRIPTOR_CONTROL const mutable = SE_DACL_AUTO_INHERIT_REQ | SE_SACL_AUTO_INHERIT_REQ | SE_DACL_AUTO_INHERITED | SE_SACL_AUTO_INHERITED | SE_DACL_PROTECTED | SE_SACL_PROTECTED | 0x00000040 | 0x00000080 /* not defined in winnt.h */ ; SECURITY_DESCRIPTOR_CONTROL const immutable = SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED | SE_DACL_PRESENT | SE_DACL_DEFAULTED | SE_SACL_PRESENT | SE_SACL_DEFAULTED | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE ;
int bit; DWORD dwRevision; LPCSTR fmt = "Expected error %s, got %u\n";
GetSecurityDescriptorControl (sec, &ref, &dwRevision);
/* The mutable bits are mutable regardless of the truth of SE_DACL_PRESENT and/or SE_SACL_PRESENT */
/* Check call barfs if any bit-of-interest is immutable */ for (bit = 0; bit < 16; ++bit) { SECURITY_DESCRIPTOR_CONTROL const bitOfInterest = 1 << bit; SECURITY_DESCRIPTOR_CONTROL setOrClear = ref & bitOfInterest;
SECURITY_DESCRIPTOR_CONTROL ctrl;
DWORD dwExpect = (bitOfInterest & immutable) ? ERROR_INVALID_PARAMETER : 0xbebecaca; LPCSTR strExpect = (bitOfInterest & immutable) ? "ERROR_INVALID_PARAMETER" : "0xbebecaca";
ctrl = (bitOfInterest & mutable) ? ref + bitOfInterest : ref; setOrClear ^= bitOfInterest; SetLastError (0xbebecaca); pSetSecurityDescriptorControl (sec, bitOfInterest, setOrClear); ok (GetLastError () == dwExpect, fmt, strExpect, GetLastError ()); GetSecurityDescriptorControl(sec, &test, &dwRevision); expect_eq(test, ctrl, int, "%x");
setOrClear ^= bitOfInterest; SetLastError (0xbebecaca); pSetSecurityDescriptorControl (sec, bitOfInterest, setOrClear); ok (GetLastError () == dwExpect, fmt, strExpect, GetLastError ()); GetSecurityDescriptorControl (sec, &test, &dwRevision); expect_eq(test, ref, int, "%x"); }
/* Check call barfs if any bit-to-set is immutable even when not a bit-of-interest */ for (bit = 0; bit < 16; ++bit) { SECURITY_DESCRIPTOR_CONTROL const bitsOfInterest = mutable; SECURITY_DESCRIPTOR_CONTROL setOrClear = ref & bitsOfInterest;
SECURITY_DESCRIPTOR_CONTROL ctrl;
DWORD dwExpect = ((1 << bit) & immutable) ? ERROR_INVALID_PARAMETER : 0xbebecaca; LPCSTR strExpect = ((1 << bit) & immutable) ? "ERROR_INVALID_PARAMETER" : "0xbebecaca";
ctrl = ((1 << bit) & immutable) ? test : ref | mutable; setOrClear ^= bitsOfInterest; SetLastError (0xbebecaca); pSetSecurityDescriptorControl (sec, bitsOfInterest, setOrClear | (1 << bit)); ok (GetLastError () == dwExpect, fmt, strExpect, GetLastError ()); GetSecurityDescriptorControl(sec, &test, &dwRevision); expect_eq(test, ctrl, int, "%x");
ctrl = ((1 << bit) & immutable) ? test : ref | (1 << bit); setOrClear ^= bitsOfInterest; SetLastError (0xbebecaca); pSetSecurityDescriptorControl (sec, bitsOfInterest, setOrClear | (1 << bit)); ok (GetLastError () == dwExpect, fmt, strExpect, GetLastError ()); GetSecurityDescriptorControl(sec, &test, &dwRevision); expect_eq(test, ctrl, int, "%x"); }}
static void test_PrivateObjectSecurity(void){ SECURITY_INFORMATION sec_info = OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION; SECURITY_DESCRIPTOR_CONTROL ctrl; PSECURITY_DESCRIPTOR sec; DWORD dwDescSize; DWORD dwRevision; DWORD retSize; LPSTR string; ULONG len; PSECURITY_DESCRIPTOR buf; BOOL ret;
if (!pConvertStringSecurityDescriptorToSecurityDescriptorA) { win_skip("ConvertStringSecurityDescriptorToSecurityDescriptor is not available\n"); return; }
ok(pConvertStringSecurityDescriptorToSecurityDescriptorA( "O:SY" "G:S-1-5-21-93476-23408-4576" "D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)" "(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)" "S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)", SDDL_REVISION_1, &sec, &dwDescSize), "Creating descriptor failed\n");
test_SetSecurityDescriptorControl(sec);
LocalFree(sec);
ok(pConvertStringSecurityDescriptorToSecurityDescriptorA( "O:SY" "G:S-1-5-21-93476-23408-4576", SDDL_REVISION_1, &sec, &dwDescSize), "Creating descriptor failed\n");
test_SetSecurityDescriptorControl(sec);
LocalFree(sec);
ok(pConvertStringSecurityDescriptorToSecurityDescriptorA( "O:SY" "G:S-1-5-21-93476-23408-4576" "D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)" "S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)", SDDL_REVISION_1, &sec, &dwDescSize), "Creating descriptor failed\n"); buf = HeapAlloc(GetProcessHeap(), 0, dwDescSize); pSetSecurityDescriptorControl(sec, SE_DACL_PROTECTED, SE_DACL_PROTECTED); GetSecurityDescriptorControl(sec, &ctrl, &dwRevision); expect_eq(ctrl, 0x9014, int, "%x");
ret = GetPrivateObjectSecurity(sec, GROUP_SECURITY_INFORMATION, buf, dwDescSize, &retSize); ok(ret, "GetPrivateObjectSecurity failed (err=%u)\n", GetLastError()); ok(retSize <= dwDescSize, "Buffer too small (%d vs %d)\n", retSize, dwDescSize); ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(buf, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n"); CHECK_RESULT_AND_FREE("G:S-1-5-21-93476-23408-4576"); GetSecurityDescriptorControl(buf, &ctrl, &dwRevision); expect_eq(ctrl, 0x8000, int, "%x");
ret = GetPrivateObjectSecurity(sec, GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, buf, dwDescSize, &retSize); ok(ret, "GetPrivateObjectSecurity failed (err=%u)\n", GetLastError()); ok(retSize <= dwDescSize, "Buffer too small (%d vs %d)\n", retSize, dwDescSize); ret = pConvertSecurityDescriptorToStringSecurityDescriptorA(buf, SDDL_REVISION_1, sec_info, &string, &len); ok(ret, "Conversion failed err=%u\n", GetLastError()); CHECK_ONE_OF_AND_FREE("G:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)", "G:S-1-5-21-93476-23408-4576D:P(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)"); /* Win7 */ GetSecurityDescriptorControl(buf, &ctrl, &dwRevision); expect_eq(ctrl & (~ SE_DACL_PROTECTED), 0x8004, int, "%x");
ret = GetPrivateObjectSecurity(sec, sec_info, buf, dwDescSize, &retSize); ok(ret, "GetPrivateObjectSecurity failed (err=%u)\n", GetLastError()); ok(retSize == dwDescSize, "Buffer too small (%d vs %d)\n", retSize, dwDescSize); ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(buf, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n"); CHECK_ONE_OF_AND_FREE("O:SY" "G:S-1-5-21-93476-23408-4576" "D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)" "S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)", "O:SY" "G:S-1-5-21-93476-23408-4576" "D:P(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)" "S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)"); /* Win7 */ GetSecurityDescriptorControl(buf, &ctrl, &dwRevision); expect_eq(ctrl & (~ SE_DACL_PROTECTED), 0x8014, int, "%x");
SetLastError(0xdeadbeef); ok(GetPrivateObjectSecurity(sec, sec_info, buf, 5, &retSize) == FALSE, "GetPrivateObjectSecurity should have failed\n"); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected error ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
LocalFree(sec); HeapFree(GetProcessHeap(), 0, buf);}#undef CHECK_RESULT_AND_FREE#undef CHECK_ONE_OF_AND_FREE
static void test_acls(void){ char buffer[256]; PACL pAcl = (PACL)buffer; BOOL ret;
SetLastError(0xdeadbeef); ret = InitializeAcl(pAcl, sizeof(ACL) - 1, ACL_REVISION); if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) { win_skip("InitializeAcl is not implemented\n"); return; }
ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "InitializeAcl with too small a buffer should have failed with ERROR_INSUFFICIENT_BUFFER instead of %d\n", GetLastError());
SetLastError(0xdeadbeef); ret = InitializeAcl(pAcl, 0xffffffff, ACL_REVISION); ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "InitializeAcl with too large a buffer should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GetLastError());
SetLastError(0xdeadbeef); ret = InitializeAcl(pAcl, sizeof(buffer), ACL_REVISION1); ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "InitializeAcl(ACL_REVISION1) should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GetLastError());
ret = InitializeAcl(pAcl, sizeof(buffer), ACL_REVISION2); ok(ret, "InitializeAcl(ACL_REVISION2) failed with error %d\n", GetLastError());
ret = IsValidAcl(pAcl); ok(ret, "IsValidAcl failed with error %d\n", GetLastError());
ret = InitializeAcl(pAcl, sizeof(buffer), ACL_REVISION3); ok(ret, "InitializeAcl(ACL_REVISION3) failed with error %d\n", GetLastError());
ret = IsValidAcl(pAcl); ok(ret, "IsValidAcl failed with error %d\n", GetLastError());
SetLastError(0xdeadbeef); ret = InitializeAcl(pAcl, sizeof(buffer), ACL_REVISION4); if (GetLastError() != ERROR_INVALID_PARAMETER) { ok(ret, "InitializeAcl(ACL_REVISION4) failed with error %d\n", GetLastError());
ret = IsValidAcl(pAcl); ok(ret, "IsValidAcl failed with error %d\n", GetLastError()); } else win_skip("ACL_REVISION4 is not implemented on NT4\n");
SetLastError(0xdeadbeef); ret = InitializeAcl(pAcl, sizeof(buffer), -1); ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "InitializeAcl(-1) failed with error %d\n", GetLastError());}
static void test_GetSecurityInfo(void){ char domain_users_ptr[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES]; char b[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES]; char admin_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES], dacl[100]; PSID domain_users_sid = (PSID) domain_users_ptr, domain_sid; SID_IDENTIFIER_AUTHORITY sia = { SECURITY_NT_AUTHORITY }; int domain_users_ace_id = -1, admins_ace_id = -1, i; DWORD sid_size = sizeof(admin_ptr), l = sizeof(b); PSID admin_sid = (PSID) admin_ptr, user_sid; char sd[SECURITY_DESCRIPTOR_MIN_LENGTH]; BOOL owner_defaulted, group_defaulted; BOOL dacl_defaulted, dacl_present; ACL_SIZE_INFORMATION acl_size; PSECURITY_DESCRIPTOR pSD; ACCESS_ALLOWED_ACE *ace; HANDLE token, obj; PSID owner, group; BOOL bret = TRUE; PACL pDacl; BYTE flags; DWORD ret;
if (!pGetSecurityInfo || !pSetSecurityInfo) { win_skip("[Get|Set]SecurityInfo is not available\n"); return; }
if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token)) { if (GetLastError() != ERROR_NO_TOKEN) bret = FALSE; else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) bret = FALSE; } if (!bret) { win_skip("Failed to get current user token\n"); return; } bret = GetTokenInformation(token, TokenUser, b, l, &l); ok(bret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError()); CloseHandle( token ); user_sid = ((TOKEN_USER *)b)->User.Sid;
/* Create something. Files have lots of associated security info. */ obj = CreateFileA(myARGV[0], GENERIC_READ|WRITE_DAC, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (obj == INVALID_HANDLE_VALUE) { skip("Couldn't create an object for GetSecurityInfo test\n"); return; }
ret = pGetSecurityInfo(obj, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, &owner, &group, &pDacl, NULL, &pSD); if (ret == ERROR_CALL_NOT_IMPLEMENTED) { win_skip("GetSecurityInfo is not implemented\n"); CloseHandle(obj); return; } ok(ret == ERROR_SUCCESS, "GetSecurityInfo returned %d\n", ret); ok(pSD != NULL, "GetSecurityInfo\n"); ok(owner != NULL, "GetSecurityInfo\n"); ok(group != NULL, "GetSecurityInfo\n"); if (pDacl != NULL) ok(IsValidAcl(pDacl), "GetSecurityInfo\n"); else win_skip("No ACL information returned\n");
LocalFree(pSD);
if (!pCreateWellKnownSid) { win_skip("NULL parameter test would crash on NT4\n"); CloseHandle(obj); return; }
/* If we don't ask for the security descriptor, Windows will still give us the other stuff, leaving us no way to free it. */ ret = pGetSecurityInfo(obj, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, &owner, &group, &pDacl, NULL, NULL); ok(ret == ERROR_SUCCESS, "GetSecurityInfo returned %d\n", ret); ok(owner != NULL, "GetSecurityInfo\n"); ok(group != NULL, "GetSecurityInfo\n"); if (pDacl != NULL) ok(IsValidAcl(pDacl), "GetSecurityInfo\n"); else win_skip("No ACL information returned\n");
/* Create security descriptor information and test that it comes back the same */ pSD = &sd; pDacl = (PACL)&dacl; InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION); pCreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, &sid_size); bret = InitializeAcl(pDacl, sizeof(dacl), ACL_REVISION); ok(bret, "Failed to initialize ACL.\n"); bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid); ok(bret, "Failed to add Current User to ACL.\n"); bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, admin_sid); ok(bret, "Failed to add Administrator Group to ACL.\n"); bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE); ok(bret, "Failed to add ACL to security descriptor.\n"); ret = pSetSecurityInfo(obj, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pDacl, NULL); ok(ret == ERROR_SUCCESS, "SetSecurityInfo returned %d\n", ret); ret = pGetSecurityInfo(obj, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pDacl, NULL, &pSD); ok(ret == ERROR_SUCCESS, "GetSecurityInfo returned %d\n", ret); ok(pDacl && IsValidAcl(pDacl), "GetSecurityInfo returned invalid DACL.\n"); bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation); ok(bret, "GetAclInformation failed\n"); if (acl_size.AceCount > 0) { bret = pGetAce(pDacl, 0, (VOID **)&ace); ok(bret, "Failed to get Current User ACE.\n"); bret = EqualSid(&ace->SidStart, user_sid); ok(bret, "Current User ACE (%s) != Current User SID (%s).\n", debugstr_sid(&ace->SidStart), debugstr_sid(user_sid)); ok(((ACE_HEADER *)ace)->AceFlags == 0, "Current User ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags); ok(ace->Mask == 0x1f01ff, "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask); } if (acl_size.AceCount > 1) { bret = pGetAce(pDacl, 1, (VOID **)&ace); ok(bret, "Failed to get Administators Group ACE.\n"); bret = EqualSid(&ace->SidStart, admin_sid); ok(bret, "Administators Group ACE (%s) != Administators Group SID (%s).\n", debugstr_sid(&ace->SidStart), debugstr_sid(admin_sid)); ok(((ACE_HEADER *)ace)->AceFlags == 0, "Administators Group ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags); ok(ace->Mask == 0x1f01ff, "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask); } LocalFree(pSD); CloseHandle(obj);
/* Obtain the "domain users" SID from the user SID */ if (!AllocateAndInitializeSid(&sia, 4, *GetSidSubAuthority(user_sid, 0), *GetSidSubAuthority(user_sid, 1), *GetSidSubAuthority(user_sid, 2), *GetSidSubAuthority(user_sid, 3), 0, 0, 0, 0, &domain_sid)) { win_skip("Failed to get current domain SID\n"); return; } sid_size = sizeof(domain_users_ptr); pCreateWellKnownSid(WinAccountDomainUsersSid, domain_sid, domain_users_sid, &sid_size); FreeSid(domain_sid);
/* Test querying the ownership of a process */ ret = pGetSecurityInfo(GetCurrentProcess(), SE_KERNEL_OBJECT, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &pSD); ok(!ret, "GetNamedSecurityInfo failed with error %d\n", ret);
bret = GetSecurityDescriptorOwner(pSD, &owner, &owner_defaulted); ok(bret, "GetSecurityDescriptorOwner failed with error %d\n", GetLastError()); ok(owner != NULL, "owner should not be NULL\n"); ok(EqualSid(owner, admin_sid) || EqualSid(owner, user_sid), "Process owner SID != Administrators SID.\n");
bret = GetSecurityDescriptorGroup(pSD, &group, &group_defaulted); ok(bret, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError()); ok(group != NULL, "group should not be NULL\n"); ok(EqualSid(group, domain_users_sid), "Process group SID != Domain Users SID.\n"); LocalFree(pSD);
/* Test querying the DACL of a process */ ret = pGetSecurityInfo(GetCurrentProcess(), SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &pSD); ok(!ret, "GetSecurityInfo failed with error %d\n", ret);
bret = GetSecurityDescriptorDacl(pSD, &dacl_present, &pDacl, &dacl_defaulted); ok(bret, "GetSecurityDescriptorDacl failed with error %d\n", GetLastError()); ok(dacl_present, "DACL should be present\n"); ok(pDacl && IsValidAcl(pDacl), "GetSecurityDescriptorDacl returned invalid DACL.\n"); bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation); ok(bret, "GetAclInformation failed\n"); ok(acl_size.AceCount != 0, "GetAclInformation returned no ACLs\n"); for (i=0; i<acl_size.AceCount; i++) { bret = pGetAce(pDacl, i, (VOID **)&ace); ok(bret, "Failed to get ACE %d.\n", i); bret = EqualSid(&ace->SidStart, domain_users_sid); if (bret) domain_users_ace_id = i; bret = EqualSid(&ace->SidStart, admin_sid); if (bret) admins_ace_id = i; } ok(domain_users_ace_id != -1 || broken(domain_users_ace_id == -1) /* win2k */, "Domain Users ACE not found.\n"); if (domain_users_ace_id != -1) { bret = pGetAce(pDacl, domain_users_ace_id, (VOID **)&ace); ok(bret, "Failed to get Domain Users ACE.\n"); flags = ((ACE_HEADER *)ace)->AceFlags; ok(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE), "Domain Users ACE has unexpected flags (0x%x != 0x%x)\n", flags, INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE); ok(ace->Mask == GENERIC_READ, "Domain Users ACE has unexpected mask (0x%x != 0x%x)\n", ace->Mask, GENERIC_READ); } ok(admins_ace_id != -1 || broken(admins_ace_id == -1) /* xp */, "Builtin Admins ACE not found.\n"); if (admins_ace_id != -1) { bret = pGetAce(pDacl, admins_ace_id, (VOID **)&ace); ok(bret, "Failed to get Builtin Admins ACE.\n"); flags = ((ACE_HEADER *)ace)->AceFlags; ok(flags == 0x0, "Builtin Admins ACE has unexpected flags (0x%x != 0x0)\n", flags); ok(ace->Mask == PROCESS_ALL_ACCESS || broken(ace->Mask == 0x1f0fff) /* win2k */, "Builtin Admins ACE has unexpected mask (0x%x != 0x%x)\n", ace->Mask, PROCESS_ALL_ACCESS); } LocalFree(pSD);}
static void test_GetSidSubAuthority(void){ PSID psid = NULL;
if (!pGetSidSubAuthority || !pConvertStringSidToSidA || !pIsValidSid || !pGetSidSubAuthorityCount) { win_skip("Some functions not available\n"); return; } /* Note: on windows passing in an invalid index like -1, lets GetSidSubAuthority return 0x05000000 but still GetLastError returns ERROR_SUCCESS then. We don't test these unlikely cornercases here for now */ ok(pConvertStringSidToSidA("S-1-5-21-93476-23408-4576",&psid),"ConvertStringSidToSidA failed\n"); ok(pIsValidSid(psid),"Sid is not valid\n"); SetLastError(0xbebecaca); ok(*pGetSidSubAuthorityCount(psid) == 4,"GetSidSubAuthorityCount gave %d expected 4\n",*pGetSidSubAuthorityCount(psid)); ok(GetLastError() == 0,"GetLastError returned %d instead of 0\n",GetLastError()); SetLastError(0xbebecaca); ok(*pGetSidSubAuthority(psid,0) == 21,"GetSidSubAuthority gave %d expected 21\n",*pGetSidSubAuthority(psid,0)); ok(GetLastError() == 0,"GetLastError returned %d instead of 0\n",GetLastError()); SetLastError(0xbebecaca); ok(*pGetSidSubAuthority(psid,1) == 93476,"GetSidSubAuthority gave %d expected 93476\n",*pGetSidSubAuthority(psid,1)); ok(GetLastError() == 0,"GetLastError returned %d instead of 0\n",GetLastError()); SetLastError(0xbebecaca); ok(pGetSidSubAuthority(psid,4) != NULL,"Expected out of bounds GetSidSubAuthority to return a non-NULL pointer\n"); ok(GetLastError() == 0,"GetLastError returned %d instead of 0\n",GetLastError()); LocalFree(psid);}
static void test_CheckTokenMembership(void){ PTOKEN_GROUPS token_groups; DWORD size; HANDLE process_token, token; BOOL is_member; BOOL ret; DWORD i;
if (!pCheckTokenMembership) { win_skip("CheckTokenMembership is not available\n"); return; } ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE|TOKEN_QUERY, &process_token); ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
ret = DuplicateToken(process_token, SecurityImpersonation, &token); ok(ret, "DuplicateToken failed with error %d\n", GetLastError());
/* groups */ ret = GetTokenInformation(token, TokenGroups, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenGroups) %s with error %d\n", ret ? "succeeded" : "failed", GetLastError()); token_groups = HeapAlloc(GetProcessHeap(), 0, size); ret = GetTokenInformation(token, TokenGroups, token_groups, size, &size); ok(ret, "GetTokenInformation(TokenGroups) failed with error %d\n", GetLastError());
for (i = 0; i < token_groups->GroupCount; i++) { if (token_groups->Groups[i].Attributes & SE_GROUP_ENABLED) break; }
if (i == token_groups->GroupCount) { HeapFree(GetProcessHeap(), 0, token_groups); CloseHandle(token); skip("user not a member of any group\n"); return; }
is_member = FALSE; ret = pCheckTokenMembership(token, token_groups->Groups[i].Sid, &is_member); ok(ret, "CheckTokenMembership failed with error %d\n", GetLastError()); ok(is_member, "CheckTokenMembership should have detected sid as member\n");
is_member = FALSE; ret = pCheckTokenMembership(NULL, token_groups->Groups[i].Sid, &is_member); ok(ret, "CheckTokenMembership failed with error %d\n", GetLastError()); ok(is_member, "CheckTokenMembership should have detected sid as member\n");
is_member = TRUE; SetLastError(0xdeadbeef); ret = pCheckTokenMembership(process_token, token_groups->Groups[i].Sid, &is_member); ok(!ret && GetLastError() == ERROR_NO_IMPERSONATION_TOKEN, "CheckTokenMembership with process token %s with error %d\n", ret ? "succeeded" : "failed", GetLastError()); ok(!is_member, "CheckTokenMembership should have cleared is_member\n");
HeapFree(GetProcessHeap(), 0, token_groups); CloseHandle(token); CloseHandle(process_token);}
static void test_EqualSid(void){ PSID sid1, sid2; BOOL ret; SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY }; SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
SetLastError(0xdeadbeef); ret = AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &sid1); if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) { win_skip("AllocateAndInitializeSid is not implemented\n"); return; } ok(ret, "AllocateAndInitializeSid failed with error %d\n", GetLastError()); ok(GetLastError() == 0xdeadbeef, "AllocateAndInitializeSid shouldn't have set last error to %d\n", GetLastError());
ret = AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &sid2); ok(ret, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
SetLastError(0xdeadbeef); ret = EqualSid(sid1, sid2); ok(!ret, "World and domain admins sids shouldn't have been equal\n"); ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef), /* NT4 */ "EqualSid should have set last error to ERROR_SUCCESS instead of %d\n", GetLastError());
SetLastError(0xdeadbeef); sid2 = FreeSid(sid2); ok(!sid2, "FreeSid should have returned NULL instead of %p\n", sid2); ok(GetLastError() == 0xdeadbeef, "FreeSid shouldn't have set last error to %d\n", GetLastError());
ret = AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &sid2); ok(ret, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
SetLastError(0xdeadbeef); ret = EqualSid(sid1, sid2); ok(ret, "Same sids should have been equal %s != %s\n", debugstr_sid(sid1), debugstr_sid(sid2)); ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef), /* NT4 */ "EqualSid should have set last error to ERROR_SUCCESS instead of %d\n", GetLastError());
((SID *)sid2)->Revision = 2; SetLastError(0xdeadbeef); ret = EqualSid(sid1, sid2); ok(!ret, "EqualSid with invalid sid should have returned FALSE\n"); ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef), /* NT4 */ "EqualSid should have set last error to ERROR_SUCCESS instead of %d\n", GetLastError()); ((SID *)sid2)->Revision = SID_REVISION;
FreeSid(sid1); FreeSid(sid2);}
static void test_GetUserNameA(void){ char buffer[UNLEN + 1], filler[UNLEN + 1]; DWORD required_len, buffer_len; BOOL ret;
/* Test crashes on Windows. */ if (0) { SetLastError(0xdeadbeef); GetUserNameA(NULL, NULL); }
SetLastError(0xdeadbeef); required_len = 0; ret = GetUserNameA(NULL, &required_len); ok(ret == FALSE, "GetUserNameA returned %d\n", ret); ok(required_len != 0, "Outputted buffer length was %u\n", required_len); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %u\n", GetLastError());
SetLastError(0xdeadbeef); required_len = 1; ret = GetUserNameA(NULL, &required_len); ok(ret == FALSE, "GetUserNameA returned %d\n", ret); ok(required_len != 0 && required_len != 1, "Outputted buffer length was %u\n", required_len); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %u\n", GetLastError());
/* Tests crashes on Windows. */ if (0) { SetLastError(0xdeadbeef); required_len = UNLEN + 1; GetUserNameA(NULL, &required_len);
SetLastError(0xdeadbeef); GetUserNameA(buffer, NULL); }
memset(filler, 'x', sizeof(filler));
/* Note that GetUserNameA on XP and newer outputs the number of bytes * required for a Unicode string, which affects a test in the next block. */ SetLastError(0xdeadbeef); memcpy(buffer, filler, sizeof(filler)); required_len = 0; ret = GetUserNameA(buffer, &required_len); ok(ret == FALSE, "GetUserNameA returned %d\n", ret); ok(!memcmp(buffer, filler, sizeof(filler)), "Output buffer was altered\n"); ok(required_len != 0, "Outputted buffer length was %u\n", required_len); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %u\n", GetLastError());
SetLastError(0xdeadbeef); memcpy(buffer, filler, sizeof(filler)); buffer_len = required_len; ret = GetUserNameA(buffer, &buffer_len); ok(ret == TRUE, "GetUserNameA returned %d, last error %u\n", ret, GetLastError()); ok(memcmp(buffer, filler, sizeof(filler)) != 0, "Output buffer was untouched\n"); ok(buffer_len == required_len || broken(buffer_len == required_len / sizeof(WCHAR)), /* XP+ */ "Outputted buffer length was %u\n", buffer_len);
/* Use the reported buffer size from the last GetUserNameA call and pass * a length that is one less than the required value. */ SetLastError(0xdeadbeef); memcpy(buffer, filler, sizeof(filler)); buffer_len--; ret = GetUserNameA(buffer, &buffer_len); ok(ret == FALSE, "GetUserNameA returned %d\n", ret); ok(!memcmp(buffer, filler, sizeof(filler)), "Output buffer was untouched\n"); ok(buffer_len == required_len, "Outputted buffer length was %u\n", buffer_len); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %u\n", GetLastError());}
static void test_GetUserNameW(void){ WCHAR buffer[UNLEN + 1], filler[UNLEN + 1]; DWORD required_len, buffer_len; BOOL ret;
/* Test crashes on Windows. */ if (0) { SetLastError(0xdeadbeef); GetUserNameW(NULL, NULL); }
SetLastError(0xdeadbeef); required_len = 0; ret = GetUserNameW(NULL, &required_len); ok(ret == FALSE, "GetUserNameW returned %d\n", ret); ok(required_len != 0, "Outputted buffer length was %u\n", required_len); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %u\n", GetLastError());
SetLastError(0xdeadbeef); required_len = 1; ret = GetUserNameW(NULL, &required_len); ok(ret == FALSE, "GetUserNameW returned %d\n", ret); ok(required_len != 0 && required_len != 1, "Outputted buffer length was %u\n", required_len); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %u\n", GetLastError());
/* Tests crash on Windows. */ if (0) { SetLastError(0xdeadbeef); required_len = UNLEN + 1; GetUserNameW(NULL, &required_len);
SetLastError(0xdeadbeef); GetUserNameW(buffer, NULL); }
memset(filler, 'x', sizeof(filler));
SetLastError(0xdeadbeef); memcpy(buffer, filler, sizeof(filler)); required_len = 0; ret = GetUserNameW(buffer, &required_len); ok(ret == FALSE, "GetUserNameW returned %d\n", ret); ok(!memcmp(buffer, filler, sizeof(filler)), "Output buffer was altered\n"); ok(required_len != 0, "Outputted buffer length was %u\n", required_len); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %u\n", GetLastError());
SetLastError(0xdeadbeef); memcpy(buffer, filler, sizeof(filler)); buffer_len = required_len; ret = GetUserNameW(buffer, &buffer_len); ok(ret == TRUE, "GetUserNameW returned %d, last error %u\n", ret, GetLastError()); ok(memcmp(buffer, filler, sizeof(filler)) != 0, "Output buffer was untouched\n"); ok(buffer_len == required_len, "Outputted buffer length was %u\n", buffer_len);
/* GetUserNameW on XP and newer writes a truncated portion of the username string to the buffer. */ SetLastError(0xdeadbeef); memcpy(buffer, filler, sizeof(filler)); buffer_len--; ret = GetUserNameW(buffer, &buffer_len); ok(ret == FALSE, "GetUserNameW returned %d\n", ret); ok(!memcmp(buffer, filler, sizeof(filler)) || broken(memcmp(buffer, filler, sizeof(filler)) != 0), /* XP+ */ "Output buffer was altered\n"); ok(buffer_len == required_len, "Outputted buffer length was %u\n", buffer_len); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %u\n", GetLastError());}
static void test_CreateRestrictedToken(void){ TOKEN_PRIMARY_GROUP *primary_group, *primary_group2; HANDLE process_token, token, r_token; PTOKEN_GROUPS token_groups, groups2; SID_AND_ATTRIBUTES sattr; SECURITY_IMPERSONATION_LEVEL level; TOKEN_PRIVILEGES *privs; PRIVILEGE_SET privset; TOKEN_TYPE type; BOOL is_member; DWORD size; BOOL ret; DWORD i, j;
if (!pCreateRestrictedToken) { win_skip("CreateRestrictedToken is not available\n"); return; }
ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE|TOKEN_QUERY, &process_token); ok(ret, "got error %d\n", GetLastError());
ret = DuplicateTokenEx(process_token, TOKEN_DUPLICATE|TOKEN_ADJUST_GROUPS|TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, NULL, SecurityImpersonation, TokenImpersonation, &token); ok(ret, "got error %d\n", GetLastError());
/* groups */ ret = GetTokenInformation(token, TokenGroups, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d with error %d\n", ret, GetLastError()); token_groups = HeapAlloc(GetProcessHeap(), 0, size); ret = GetTokenInformation(token, TokenGroups, token_groups, size, &size); ok(ret, "got error %d\n", GetLastError());
for (i = 0; i < token_groups->GroupCount; i++) { if (token_groups->Groups[i].Attributes & SE_GROUP_ENABLED) break; }
if (i == token_groups->GroupCount) { HeapFree(GetProcessHeap(), 0, token_groups); CloseHandle(token); skip("User not a member of any group\n"); return; }
is_member = FALSE; ret = pCheckTokenMembership(token, token_groups->Groups[i].Sid, &is_member); ok(ret, "got error %d\n", GetLastError()); ok(is_member, "not a member\n");
privset.PrivilegeCount = 1; privset.Control = PRIVILEGE_SET_ALL_NECESSARY; ret = LookupPrivilegeValueA(NULL, "SeChangeNotifyPrivilege", &privset.Privilege[0].Luid); ok(ret, "got error %d\n", GetLastError());
is_member = FALSE; ret = PrivilegeCheck(token, &privset, &is_member); ok(ret, "got error %d\n", GetLastError()); ok(is_member, "Expected SeChangeNotifyPrivilege to be enabled\n");
/* disable a SID and a privilege in new token */ sattr.Sid = token_groups->Groups[i].Sid; sattr.Attributes = 0; r_token = NULL; ret = pCreateRestrictedToken(token, 0, 1, &sattr, 1, &privset.Privilege[0], 0, NULL, &r_token); ok(ret, "got error %d\n", GetLastError());
if (ret) { /* check if a SID is enabled */ is_member = TRUE; ret = pCheckTokenMembership(r_token, token_groups->Groups[i].Sid, &is_member); ok(ret, "got error %d\n", GetLastError()); ok(!is_member, "not a member\n");
ret = GetTokenInformation(r_token, TokenGroups, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d with error %d\n", ret, GetLastError()); groups2 = HeapAlloc(GetProcessHeap(), 0, size); ret = GetTokenInformation(r_token, TokenGroups, groups2, size, &size); ok(ret, "got error %d\n", GetLastError());
for (j = 0; j < groups2->GroupCount; j++) { if (EqualSid(groups2->Groups[j].Sid, token_groups->Groups[i].Sid)) break; }
ok(groups2->Groups[j].Attributes & SE_GROUP_USE_FOR_DENY_ONLY, "got wrong attributes\n"); ok((groups2->Groups[j].Attributes & SE_GROUP_ENABLED) == 0, "got wrong attributes\n");
HeapFree(GetProcessHeap(), 0, groups2);
size = sizeof(type); ret = GetTokenInformation(r_token, TokenType, &type, size, &size); ok(ret, "got error %d\n", GetLastError()); ok(type == TokenImpersonation, "got type %u\n", type);
size = sizeof(level); ret = GetTokenInformation(r_token, TokenImpersonationLevel, &level, size, &size); ok(ret, "got error %d\n", GetLastError()); ok(level == SecurityImpersonation, "got level %u\n", type);
is_member = TRUE; ret = PrivilegeCheck(r_token, &privset, &is_member); ok(ret, "got error %d\n", GetLastError()); ok(!is_member, "Expected SeChangeNotifyPrivilege not to be enabled\n");
ret = GetTokenInformation(r_token, TokenPrivileges, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d with error %d\n", ret, GetLastError()); privs = HeapAlloc(GetProcessHeap(), 0, size); ret = GetTokenInformation(r_token, TokenPrivileges, privs, size, &size); ok(ret, "got error %d\n", GetLastError());
is_member = FALSE; for (j = 0; j < privs->PrivilegeCount; j++) { if (RtlEqualLuid(&privs->Privileges[j].Luid, &privset.Privilege[0].Luid)) { is_member = TRUE; break; } }
ok(!is_member, "Expected not to find privilege\n"); HeapFree(GetProcessHeap(), 0, privs); }
HeapFree(GetProcessHeap(), 0, token_groups); CloseHandle(r_token);
ret = GetTokenInformation(token, TokenPrimaryGroup, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d with error %d\n", ret, GetLastError()); primary_group = HeapAlloc(GetProcessHeap(), 0, size); ret = GetTokenInformation(token, TokenPrimaryGroup, primary_group, size, &size); ok(ret, "got error %d\n", GetLastError());
/* disable primary group */ sattr.Sid = primary_group->PrimaryGroup; sattr.Attributes = 0; r_token = NULL; ret = pCreateRestrictedToken(token, 0, 1, &sattr, 0, NULL, 0, NULL, &r_token); ok(ret, "got error %d\n", GetLastError());
if (ret) { is_member = TRUE; ret = pCheckTokenMembership(r_token, primary_group->PrimaryGroup, &is_member); ok(ret, "got error %d\n", GetLastError()); ok(!is_member, "not a member\n");
ret = GetTokenInformation(r_token, TokenPrimaryGroup, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d with error %d\n", ret, GetLastError()); primary_group2 = HeapAlloc(GetProcessHeap(), 0, size); ret = GetTokenInformation(r_token, TokenPrimaryGroup, primary_group2, size, &size); ok(ret, "got error %d\n", GetLastError());
ok(EqualSid(primary_group2->PrimaryGroup, primary_group->PrimaryGroup), "Expected same primary group\n");
HeapFree(GetProcessHeap(), 0, primary_group2); }
HeapFree(GetProcessHeap(), 0, primary_group); CloseHandle(r_token);
CloseHandle(token); CloseHandle(process_token);}
static void validate_default_security_descriptor(SECURITY_DESCRIPTOR *sd){ BOOL ret, present, defaulted; ACL *acl; void *sid;
ret = IsValidSecurityDescriptor(sd); ok(ret, "security descriptor is not valid\n");
present = -1; defaulted = -1; acl = (void *)0xdeadbeef; SetLastError(0xdeadbeef); ret = GetSecurityDescriptorDacl(sd, &present, &acl, &defaulted); ok(ret, "GetSecurityDescriptorDacl error %d\n", GetLastError());todo_wine ok(present == 1, "acl is not present\n");todo_wine ok(acl != (void *)0xdeadbeef && acl != NULL, "acl pointer is not set\n"); ok(defaulted == 0, "defaulted is set to TRUE\n");
defaulted = -1; sid = (void *)0xdeadbeef; SetLastError(0xdeadbeef); ret = GetSecurityDescriptorOwner(sd, &sid, &defaulted); ok(ret, "GetSecurityDescriptorOwner error %d\n", GetLastError());todo_wine ok(sid != (void *)0xdeadbeef && sid != NULL, "sid pointer is not set\n"); ok(defaulted == 0, "defaulted is set to TRUE\n");
defaulted = -1; sid = (void *)0xdeadbeef; SetLastError(0xdeadbeef); ret = GetSecurityDescriptorGroup(sd, &sid, &defaulted); ok(ret, "GetSecurityDescriptorGroup error %d\n", GetLastError());todo_wine ok(sid != (void *)0xdeadbeef && sid != NULL, "sid pointer is not set\n"); ok(defaulted == 0, "defaulted is set to TRUE\n");}
static void test_default_handle_security(HANDLE token, HANDLE handle, GENERIC_MAPPING *mapping){ DWORD ret, granted, priv_set_len; BOOL status; PRIVILEGE_SET priv_set; SECURITY_DESCRIPTOR *sd;
sd = test_get_security_descriptor(handle, __LINE__); validate_default_security_descriptor(sd);
priv_set_len = sizeof(priv_set); granted = 0xdeadbeef; status = 0xdeadbeef; SetLastError(0xdeadbeef); ret = AccessCheck(sd, token, MAXIMUM_ALLOWED, mapping, &priv_set, &priv_set_len, &granted, &status);todo_wine { ok(ret, "AccessCheck error %d\n", GetLastError()); ok(status == 1, "expected 1, got %d\n", status); ok(granted == mapping->GenericAll, "expected all access %#x, got %#x\n", mapping->GenericAll, granted);} priv_set_len = sizeof(priv_set); granted = 0xdeadbeef; status = 0xdeadbeef; SetLastError(0xdeadbeef); ret = AccessCheck(sd, token, 0, mapping, &priv_set, &priv_set_len, &granted, &status);todo_wine { ok(ret, "AccessCheck error %d\n", GetLastError()); ok(status == 0 || broken(status == 1) /* NT4 */, "expected 0, got %d\n", status); ok(granted == 0 || broken(granted == mapping->GenericRead) /* NT4 */, "expected 0, got %#x\n", granted);} priv_set_len = sizeof(priv_set); granted = 0xdeadbeef; status = 0xdeadbeef; SetLastError(0xdeadbeef); ret = AccessCheck(sd, token, ACCESS_SYSTEM_SECURITY, mapping, &priv_set, &priv_set_len, &granted, &status);todo_wine { ok(ret, "AccessCheck error %d\n", GetLastError()); ok(status == 0, "expected 0, got %d\n", status); ok(granted == 0, "expected 0, got %#x\n", granted);} priv_set_len = sizeof(priv_set); granted = 0xdeadbeef; status = 0xdeadbeef; SetLastError(0xdeadbeef); ret = AccessCheck(sd, token, mapping->GenericRead, mapping, &priv_set, &priv_set_len, &granted, &status);todo_wine { ok(ret, "AccessCheck error %d\n", GetLastError()); ok(status == 1, "expected 1, got %d\n", status); ok(granted == mapping->GenericRead, "expected read access %#x, got %#x\n", mapping->GenericRead, granted);} priv_set_len = sizeof(priv_set); granted = 0xdeadbeef; status = 0xdeadbeef; SetLastError(0xdeadbeef); ret = AccessCheck(sd, token, mapping->GenericWrite, mapping, &priv_set, &priv_set_len, &granted, &status);todo_wine { ok(ret, "AccessCheck error %d\n", GetLastError()); ok(status == 1, "expected 1, got %d\n", status); ok(granted == mapping->GenericWrite, "expected write access %#x, got %#x\n", mapping->GenericWrite, granted);} priv_set_len = sizeof(priv_set); granted = 0xdeadbeef; status = 0xdeadbeef; SetLastError(0xdeadbeef); ret = AccessCheck(sd, token, mapping->GenericExecute, mapping, &priv_set, &priv_set_len, &granted, &status);todo_wine { ok(ret, "AccessCheck error %d\n", GetLastError()); ok(status == 1, "expected 1, got %d\n", status); ok(granted == mapping->GenericExecute, "expected execute access %#x, got %#x\n", mapping->GenericExecute, granted);} HeapFree(GetProcessHeap(), 0, sd);}
static ACCESS_MASK get_obj_access(HANDLE obj){ OBJECT_BASIC_INFORMATION info; NTSTATUS status;
if (!pNtQueryObject) return 0;
status = pNtQueryObject(obj, ObjectBasicInformation, &info, sizeof(info), NULL); ok(!status, "NtQueryObject error %#x\n", status);
return info.GrantedAccess;}
static void test_mutex_security(HANDLE token){ DWORD ret, i, access; HANDLE mutex, dup; GENERIC_MAPPING mapping = { STANDARD_RIGHTS_READ | MUTANT_QUERY_STATE | SYNCHRONIZE, STANDARD_RIGHTS_WRITE | MUTEX_MODIFY_STATE | SYNCHRONIZE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE, STANDARD_RIGHTS_ALL | MUTEX_ALL_ACCESS }; static const struct { int generic, mapped; } map[] = { { 0, 0 }, { GENERIC_READ, STANDARD_RIGHTS_READ | MUTANT_QUERY_STATE }, { GENERIC_WRITE, STANDARD_RIGHTS_WRITE }, { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE }, { GENERIC_ALL, STANDARD_RIGHTS_ALL | MUTANT_QUERY_STATE } };
SetLastError(0xdeadbeef); mutex = OpenMutexA(0, FALSE, "WineTestMutex"); ok(!mutex, "mutex should not exist\n"); ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
SetLastError(0xdeadbeef); mutex = CreateMutexA(NULL, FALSE, "WineTestMutex"); ok(mutex != 0, "CreateMutex error %d\n", GetLastError());
access = get_obj_access(mutex); ok(access == MUTANT_ALL_ACCESS, "expected MUTANT_ALL_ACCESS, got %#x\n", access);
for (i = 0; i < sizeof(map)/sizeof(map[0]); i++) { SetLastError( 0xdeadbeef ); ret = DuplicateHandle(GetCurrentProcess(), mutex, GetCurrentProcess(), &dup, map[i].generic, FALSE, 0); ok(ret, "DuplicateHandle error %d\n", GetLastError());
access = get_obj_access(dup); ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
CloseHandle(dup);
SetLastError(0xdeadbeef); dup = OpenMutexA(0, FALSE, "WineTestMutex");todo_wine ok(!dup, "OpenMutex should fail\n");todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError()); }
test_default_handle_security(token, mutex, &mapping);
CloseHandle (mutex);}
static void test_event_security(HANDLE token){ DWORD ret, i, access; HANDLE event, dup; GENERIC_MAPPING mapping = { STANDARD_RIGHTS_READ | EVENT_QUERY_STATE | SYNCHRONIZE, STANDARD_RIGHTS_WRITE | EVENT_MODIFY_STATE | SYNCHRONIZE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE, STANDARD_RIGHTS_ALL | EVENT_ALL_ACCESS }; static const struct { int generic, mapped; } map[] = { { 0, 0 }, { GENERIC_READ, STANDARD_RIGHTS_READ | EVENT_QUERY_STATE }, { GENERIC_WRITE, STANDARD_RIGHTS_WRITE | EVENT_MODIFY_STATE }, { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE }, { GENERIC_ALL, STANDARD_RIGHTS_ALL | EVENT_QUERY_STATE | EVENT_MODIFY_STATE } };
SetLastError(0xdeadbeef); event = OpenEventA(0, FALSE, "WineTestEvent"); ok(!event, "event should not exist\n"); ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
SetLastError(0xdeadbeef); event = CreateEventA(NULL, FALSE, FALSE, "WineTestEvent"); ok(event != 0, "CreateEvent error %d\n", GetLastError());
access = get_obj_access(event); ok(access == EVENT_ALL_ACCESS, "expected EVENT_ALL_ACCESS, got %#x\n", access);
for (i = 0; i < sizeof(map)/sizeof(map[0]); i++) { SetLastError( 0xdeadbeef ); ret = DuplicateHandle(GetCurrentProcess(), event, GetCurrentProcess(), &dup, map[i].generic, FALSE, 0); ok(ret, "DuplicateHandle error %d\n", GetLastError());
access = get_obj_access(dup); ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
CloseHandle(dup);
SetLastError(0xdeadbeef); dup = OpenEventA(0, FALSE, "WineTestEvent");todo_wine ok(!dup, "OpenEvent should fail\n");todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError()); }
test_default_handle_security(token, event, &mapping);
CloseHandle(event);}
static void test_semaphore_security(HANDLE token){ DWORD ret, i, access; HANDLE sem, dup; GENERIC_MAPPING mapping = { STANDARD_RIGHTS_READ | SEMAPHORE_QUERY_STATE, STANDARD_RIGHTS_WRITE | SEMAPHORE_MODIFY_STATE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE, STANDARD_RIGHTS_ALL | SEMAPHORE_ALL_ACCESS }; static const struct { int generic, mapped; } map[] = { { 0, 0 }, { GENERIC_READ, STANDARD_RIGHTS_READ | SEMAPHORE_QUERY_STATE }, { GENERIC_WRITE, STANDARD_RIGHTS_WRITE | SEMAPHORE_MODIFY_STATE }, { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE }, { GENERIC_ALL, STANDARD_RIGHTS_ALL | SEMAPHORE_QUERY_STATE | SEMAPHORE_MODIFY_STATE } };
SetLastError(0xdeadbeef); sem = OpenSemaphoreA(0, FALSE, "WineTestSemaphore"); ok(!sem, "semaphore should not exist\n"); ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
SetLastError(0xdeadbeef); sem = CreateSemaphoreA(NULL, 0, 10, "WineTestSemaphore"); ok(sem != 0, "CreateSemaphore error %d\n", GetLastError());
access = get_obj_access(sem); ok(access == SEMAPHORE_ALL_ACCESS, "expected SEMAPHORE_ALL_ACCESS, got %#x\n", access);
for (i = 0; i < sizeof(map)/sizeof(map[0]); i++) { SetLastError( 0xdeadbeef ); ret = DuplicateHandle(GetCurrentProcess(), sem, GetCurrentProcess(), &dup, map[i].generic, FALSE, 0); ok(ret, "DuplicateHandle error %d\n", GetLastError());
access = get_obj_access(dup); ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
CloseHandle(dup); }
test_default_handle_security(token, sem, &mapping);
CloseHandle(sem);}
#define WINE_TEST_PIPE "\\\\.\\pipe\\WineTestPipe"static void test_named_pipe_security(HANDLE token){ DWORD ret, i, access; HANDLE pipe, file, dup; GENERIC_MAPPING mapping = { FILE_GENERIC_READ, FILE_GENERIC_WRITE, FILE_GENERIC_EXECUTE, STANDARD_RIGHTS_ALL | FILE_ALL_ACCESS }; static const struct { int todo, generic, mapped; } map[] = { { 0, 0, 0 }, { 1, GENERIC_READ, FILE_GENERIC_READ }, { 1, GENERIC_WRITE, FILE_GENERIC_WRITE }, { 1, GENERIC_EXECUTE, FILE_GENERIC_EXECUTE }, { 1, GENERIC_ALL, STANDARD_RIGHTS_ALL | FILE_ALL_ACCESS } }; static const struct { DWORD open_mode; DWORD access; } creation_access[] = { { PIPE_ACCESS_INBOUND, FILE_GENERIC_READ }, { PIPE_ACCESS_OUTBOUND, FILE_GENERIC_WRITE }, { PIPE_ACCESS_DUPLEX, FILE_GENERIC_READ|FILE_GENERIC_WRITE }, { PIPE_ACCESS_INBOUND|WRITE_DAC, FILE_GENERIC_READ|WRITE_DAC }, { PIPE_ACCESS_INBOUND|WRITE_OWNER, FILE_GENERIC_READ|WRITE_OWNER } /* ACCESS_SYSTEM_SECURITY is also valid, but will fail with ERROR_PRIVILEGE_NOT_HELD */ };
/* Test the different security access options for pipes */ for (i = 0; i < sizeof(creation_access)/sizeof(creation_access[0]); i++) { SetLastError(0xdeadbeef); pipe = CreateNamedPipeA(WINE_TEST_PIPE, creation_access[i].open_mode, PIPE_TYPE_BYTE | PIPE_NOWAIT, PIPE_UNLIMITED_INSTANCES, 0, 0, NMPWAIT_USE_DEFAULT_WAIT, NULL); ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe(0x%x) error %d\n", creation_access[i].open_mode, GetLastError()); access = get_obj_access(pipe); ok(access == creation_access[i].access, "CreateNamedPipeA(0x%x) pipe expected access 0x%x (got 0x%x)\n", creation_access[i].open_mode, creation_access[i].access, access); CloseHandle(pipe); }
SetLastError(0xdeadbeef); pipe = CreateNamedPipeA(WINE_TEST_PIPE, PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, PIPE_TYPE_BYTE | PIPE_NOWAIT, PIPE_UNLIMITED_INSTANCES, 0, 0, NMPWAIT_USE_DEFAULT_WAIT, NULL); ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe error %d\n", GetLastError());
test_default_handle_security(token, pipe, &mapping);
SetLastError(0xdeadbeef); file = CreateFileA(WINE_TEST_PIPE, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING, 0, 0); ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
access = get_obj_access(file); ok(access == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#x\n", access);
for (i = 0; i < sizeof(map)/sizeof(map[0]); i++) { SetLastError( 0xdeadbeef ); ret = DuplicateHandle(GetCurrentProcess(), file, GetCurrentProcess(), &dup, map[i].generic, FALSE, 0); ok(ret, "DuplicateHandle error %d\n", GetLastError());
access = get_obj_access(dup); ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
CloseHandle(dup); }
CloseHandle(file); CloseHandle(pipe);
SetLastError(0xdeadbeef); file = CreateFileA("\\\\.\\pipe\\", FILE_ALL_ACCESS, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); ok(file != INVALID_HANDLE_VALUE || broken(file == INVALID_HANDLE_VALUE) /* before Vista */, "CreateFile error %d\n", GetLastError());
if (file != INVALID_HANDLE_VALUE) { access = get_obj_access(file); ok(access == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#x\n", access);
for (i = 0; i < sizeof(map)/sizeof(map[0]); i++) { SetLastError( 0xdeadbeef ); ret = DuplicateHandle(GetCurrentProcess(), file, GetCurrentProcess(), &dup, map[i].generic, FALSE, 0); ok(ret, "DuplicateHandle error %d\n", GetLastError());
access = get_obj_access(dup); todo_wine_if (map[i].todo) ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
CloseHandle(dup); } }
CloseHandle(file);}
static void test_file_security(HANDLE token){ DWORD ret, i, access, bytes; HANDLE file, dup; static const struct { int generic, mapped; } map[] = { { 0, 0 }, { GENERIC_READ, FILE_GENERIC_READ }, { GENERIC_WRITE, FILE_GENERIC_WRITE }, { GENERIC_EXECUTE, FILE_GENERIC_EXECUTE }, { GENERIC_ALL, STANDARD_RIGHTS_ALL | FILE_ALL_ACCESS } }; char temp_path[MAX_PATH]; char file_name[MAX_PATH]; char buf[16];
GetTempPathA(MAX_PATH, temp_path); GetTempFileNameA(temp_path, "tmp", 0, file_name);
/* file */ SetLastError(0xdeadbeef); file = CreateFileA(file_name, GENERIC_ALL, 0, NULL, CREATE_ALWAYS, 0, NULL); ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
access = get_obj_access(file); ok(access == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#x\n", access);
for (i = 0; i < sizeof(map)/sizeof(map[0]); i++) { SetLastError( 0xdeadbeef ); ret = DuplicateHandle(GetCurrentProcess(), file, GetCurrentProcess(), &dup, map[i].generic, FALSE, 0); ok(ret, "DuplicateHandle error %d\n", GetLastError());
access = get_obj_access(dup); ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
CloseHandle(dup); }
CloseHandle(file);
SetLastError(0xdeadbeef); file = CreateFileA(file_name, 0, 0, NULL, OPEN_EXISTING, 0, NULL); ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
access = get_obj_access(file);todo_wine ok(access == (FILE_READ_ATTRIBUTES | SYNCHRONIZE), "expected FILE_READ_ATTRIBUTES | SYNCHRONIZE, got %#x\n", access);
bytes = 0xdeadbeef; SetLastError(0xdeadbeef); ret = ReadFile(file, buf, sizeof(buf), &bytes, NULL); ok(!ret, "ReadFile should fail\n"); ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); ok(bytes == 0, "expected 0, got %u\n", bytes);
CloseHandle(file);
SetLastError(0xdeadbeef); file = CreateFileA(file_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0); ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
access = get_obj_access(file);todo_wine ok(access == (FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES), "expected FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES, got %#x\n", access);
bytes = 0xdeadbeef; SetLastError(0xdeadbeef); ret = ReadFile(file, buf, sizeof(buf), &bytes, NULL); ok(!ret, "ReadFile should fail\n"); ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); ok(bytes == 0, "expected 0, got %u\n", bytes);
CloseHandle(file); DeleteFileA(file_name);
/* directory */ SetLastError(0xdeadbeef); file = CreateFileA(temp_path, GENERIC_ALL, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
access = get_obj_access(file); ok(access == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#x\n", access);
for (i = 0; i < sizeof(map)/sizeof(map[0]); i++) { SetLastError( 0xdeadbeef ); ret = DuplicateHandle(GetCurrentProcess(), file, GetCurrentProcess(), &dup, map[i].generic, FALSE, 0); ok(ret, "DuplicateHandle error %d\n", GetLastError());
access = get_obj_access(dup); ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
CloseHandle(dup); }
CloseHandle(file);
SetLastError(0xdeadbeef); file = CreateFileA(temp_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
access = get_obj_access(file);todo_wine ok(access == (FILE_READ_ATTRIBUTES | SYNCHRONIZE), "expected FILE_READ_ATTRIBUTES | SYNCHRONIZE, got %#x\n", access);
CloseHandle(file);
SetLastError(0xdeadbeef); file = CreateFileA(temp_path, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
access = get_obj_access(file);todo_wine ok(access == (FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES), "expected FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES, got %#x\n", access);
CloseHandle(file);}
static void test_filemap_security(void){ char temp_path[MAX_PATH]; char file_name[MAX_PATH]; DWORD ret, i, access; HANDLE file, mapping, dup, created_mapping; static const struct { int generic, mapped; BOOL open_only; } map[] = { { 0, 0 }, { GENERIC_READ, STANDARD_RIGHTS_READ | SECTION_QUERY | SECTION_MAP_READ }, { GENERIC_WRITE, STANDARD_RIGHTS_WRITE | SECTION_MAP_WRITE }, { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SECTION_MAP_EXECUTE }, { GENERIC_ALL, STANDARD_RIGHTS_REQUIRED | SECTION_ALL_ACCESS }, { SECTION_MAP_READ | SECTION_MAP_WRITE, SECTION_MAP_READ | SECTION_MAP_WRITE }, { SECTION_MAP_WRITE, SECTION_MAP_WRITE }, { SECTION_MAP_READ | SECTION_QUERY, SECTION_MAP_READ | SECTION_QUERY }, { SECTION_QUERY, SECTION_MAP_READ, TRUE }, { SECTION_QUERY | SECTION_MAP_READ, SECTION_QUERY | SECTION_MAP_READ } }; static const struct { int prot, mapped; } prot_map[] = { { 0, 0 }, { PAGE_NOACCESS, 0 }, { PAGE_READONLY, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ }, { PAGE_READWRITE, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE }, { PAGE_WRITECOPY, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ }, { PAGE_EXECUTE, 0 }, { PAGE_EXECUTE_READ, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_EXECUTE }, { PAGE_EXECUTE_READWRITE, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE }, { PAGE_EXECUTE_WRITECOPY, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_EXECUTE } };
GetTempPathA(MAX_PATH, temp_path); GetTempFileNameA(temp_path, "tmp", 0, file_name);
SetLastError(0xdeadbeef); file = CreateFileA(file_name, GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE, 0, NULL, CREATE_ALWAYS, 0, 0); ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError()); SetFilePointer(file, 4096, NULL, FILE_BEGIN); SetEndOfFile(file);
for (i = 0; i < sizeof(prot_map)/sizeof(prot_map[0]); i++) { if (map[i].open_only) continue;
SetLastError(0xdeadbeef); mapping = CreateFileMappingW(file, NULL, prot_map[i].prot, 0, 4096, NULL); if (prot_map[i].mapped) { if (!mapping) { /* NT4 and win2k don't support EXEC on file mappings */ if (prot_map[i].prot == PAGE_EXECUTE_READ || prot_map[i].prot == PAGE_EXECUTE_READWRITE || prot_map[i].prot == PAGE_EXECUTE_WRITECOPY) { win_skip("CreateFileMapping doesn't support PAGE_EXECUTE protection\n"); continue; } } ok(mapping != 0, "CreateFileMapping(%04x) error %d\n", prot_map[i].prot, GetLastError()); } else { ok(!mapping, "CreateFileMapping(%04x) should fail\n", prot_map[i].prot); ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); continue; }
access = get_obj_access(mapping); ok(access == prot_map[i].mapped, "%d: expected %#x, got %#x\n", i, prot_map[i].mapped, access);
CloseHandle(mapping); }
SetLastError(0xdeadbeef); mapping = CreateFileMappingW(file, NULL, PAGE_EXECUTE_READWRITE, 0, 4096, NULL); if (!mapping) { /* NT4 and win2k don't support EXEC on file mappings */ win_skip("CreateFileMapping doesn't support PAGE_EXECUTE protection\n"); CloseHandle(file); DeleteFileA(file_name); return; } ok(mapping != 0, "CreateFileMapping error %d\n", GetLastError());
access = get_obj_access(mapping); ok(access == (STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE), "expected STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE, got %#x\n", access);
for (i = 0; i < sizeof(map)/sizeof(map[0]); i++) { if (map[i].open_only) continue;
SetLastError( 0xdeadbeef ); ret = DuplicateHandle(GetCurrentProcess(), mapping, GetCurrentProcess(), &dup, map[i].generic, FALSE, 0); ok(ret, "DuplicateHandle error %d\n", GetLastError());
access = get_obj_access(dup); ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
CloseHandle(dup); }
CloseHandle(mapping); CloseHandle(file); DeleteFileA(file_name);
created_mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 0x1000, "Wine Test Open Mapping"); ok(created_mapping != NULL, "CreateFileMapping failed with error %u\n", GetLastError());
for (i = 0; i < sizeof(map)/sizeof(map[0]); i++) { if (!map[i].generic) continue;
mapping = OpenFileMappingA(map[i].generic, FALSE, "Wine Test Open Mapping"); ok(mapping != NULL, "OpenFileMapping failed with error %d\n", GetLastError()); access = get_obj_access(mapping); ok(access == map[i].mapped, "%d: unexpected access flags %#x, expected %#x\n", i, access, map[i].mapped); CloseHandle(mapping); }
CloseHandle(created_mapping);}
static void test_thread_security(void){ DWORD ret, i, access; HANDLE thread, dup; static const struct { int generic, mapped; } map[] = { { 0, 0 }, { GENERIC_READ, STANDARD_RIGHTS_READ | THREAD_QUERY_INFORMATION | THREAD_GET_CONTEXT }, { GENERIC_WRITE, STANDARD_RIGHTS_WRITE | THREAD_SET_INFORMATION | THREAD_SET_CONTEXT | THREAD_TERMINATE | THREAD_SUSPEND_RESUME | 0x4 }, { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE }, { GENERIC_ALL, THREAD_ALL_ACCESS_NT4 } };
SetLastError(0xdeadbeef); thread = CreateThread(NULL, 0, (void *)0xdeadbeef, NULL, CREATE_SUSPENDED, &ret); ok(thread != 0, "CreateThread error %d\n", GetLastError());
access = get_obj_access(thread); ok(access == THREAD_ALL_ACCESS_NT4 || access == THREAD_ALL_ACCESS_VISTA, "expected THREAD_ALL_ACCESS, got %#x\n", access);
for (i = 0; i < sizeof(map)/sizeof(map[0]); i++) { SetLastError( 0xdeadbeef ); ret = DuplicateHandle(GetCurrentProcess(), thread, GetCurrentProcess(), &dup, map[i].generic, FALSE, 0); ok(ret, "DuplicateHandle error %d\n", GetLastError());
access = get_obj_access(dup); switch (map[i].generic) { case GENERIC_READ: case GENERIC_EXECUTE: ok(access == map[i].mapped || access == (map[i].mapped | THREAD_QUERY_LIMITED_INFORMATION) /* Vista+ */ || access == (map[i].mapped | THREAD_QUERY_LIMITED_INFORMATION | THREAD_RESUME) /* win8 */, "%d: expected %#x, got %#x\n", i, map[i].mapped, access); break; case GENERIC_WRITE:todo_wine ok(access == map[i].mapped || access == (map[i].mapped | THREAD_SET_LIMITED_INFORMATION) /* Vista+ */ || access == (map[i].mapped | THREAD_SET_LIMITED_INFORMATION | THREAD_RESUME) /* win8 */, "%d: expected %#x, got %#x\n", i, map[i].mapped, access); break; case GENERIC_ALL: ok(access == map[i].mapped || access == THREAD_ALL_ACCESS_VISTA, "%d: expected %#x, got %#x\n", i, map[i].mapped, access); break; default: ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access); break; }
CloseHandle(dup); }
SetLastError( 0xdeadbeef ); ret = DuplicateHandle(GetCurrentProcess(), thread, GetCurrentProcess(), &dup, THREAD_QUERY_INFORMATION, FALSE, 0); ok(ret, "DuplicateHandle error %d\n", GetLastError()); access = get_obj_access(dup); ok(access == (THREAD_QUERY_INFORMATION | THREAD_QUERY_LIMITED_INFORMATION) /* Vista+ */ || access == THREAD_QUERY_INFORMATION /* before Vista */, "expected THREAD_QUERY_INFORMATION|THREAD_QUERY_LIMITED_INFORMATION, got %#x\n", access); CloseHandle(dup);
TerminateThread(thread, 0); CloseHandle(thread);}
static void test_process_access(void){ DWORD ret, i, access; HANDLE process, dup; STARTUPINFOA sti; PROCESS_INFORMATION pi; char cmdline[] = "winver.exe"; static const struct { int generic, mapped; } map[] = { { 0, 0 }, { GENERIC_READ, STANDARD_RIGHTS_READ | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ }, { GENERIC_WRITE, STANDARD_RIGHTS_WRITE | PROCESS_SET_QUOTA | PROCESS_SET_INFORMATION | PROCESS_SUSPEND_RESUME | PROCESS_VM_WRITE | PROCESS_DUP_HANDLE | PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION }, { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE }, { GENERIC_ALL, PROCESS_ALL_ACCESS_NT4 } };
memset(&sti, 0, sizeof(sti)); sti.cb = sizeof(sti); SetLastError(0xdeadbeef); ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &sti, &pi); ok(ret, "CreateProcess() error %d\n", GetLastError());
CloseHandle(pi.hThread); process = pi.hProcess;
access = get_obj_access(process); ok(access == PROCESS_ALL_ACCESS_NT4 || access == PROCESS_ALL_ACCESS_VISTA, "expected PROCESS_ALL_ACCESS, got %#x\n", access);
for (i = 0; i < sizeof(map)/sizeof(map[0]); i++) { SetLastError( 0xdeadbeef ); ret = DuplicateHandle(GetCurrentProcess(), process, GetCurrentProcess(), &dup, map[i].generic, FALSE, 0); ok(ret, "DuplicateHandle error %d\n", GetLastError());
access = get_obj_access(dup); switch (map[i].generic) { case GENERIC_READ: ok(access == map[i].mapped || access == (map[i].mapped | PROCESS_QUERY_LIMITED_INFORMATION) /* Vista+ */, "%d: expected %#x, got %#x\n", i, map[i].mapped, access); break; case GENERIC_WRITE: ok(access == map[i].mapped || access == (map[i].mapped | PROCESS_TERMINATE) /* before Vista */ || access == (map[i].mapped | PROCESS_SET_LIMITED_INFORMATION) /* win8 */ || access == (map[i].mapped | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_SET_LIMITED_INFORMATION) /* Win10 Anniversary Update */, "%d: expected %#x, got %#x\n", i, map[i].mapped, access); break; case GENERIC_EXECUTE: ok(access == map[i].mapped || access == (map[i].mapped | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_TERMINATE) /* Vista+ */, "%d: expected %#x, got %#x\n", i, map[i].mapped, access); break; case GENERIC_ALL: ok(access == map[i].mapped || access == PROCESS_ALL_ACCESS_VISTA, "%d: expected %#x, got %#x\n", i, map[i].mapped, access); break; default: ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access); break; }
CloseHandle(dup); }
SetLastError( 0xdeadbeef ); ret = DuplicateHandle(GetCurrentProcess(), process, GetCurrentProcess(), &dup, PROCESS_QUERY_INFORMATION, FALSE, 0); ok(ret, "DuplicateHandle error %d\n", GetLastError()); access = get_obj_access(dup); ok(access == (PROCESS_QUERY_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION) /* Vista+ */ || access == PROCESS_QUERY_INFORMATION /* before Vista */, "expected PROCESS_QUERY_INFORMATION|PROCESS_QUERY_LIMITED_INFORMATION, got %#x\n", access); CloseHandle(dup);
TerminateProcess(process, 0); CloseHandle(process);}
static BOOL validate_impersonation_token(HANDLE token, DWORD *token_type){ DWORD ret, needed; TOKEN_TYPE type; SECURITY_IMPERSONATION_LEVEL sil;
type = 0xdeadbeef; needed = 0; SetLastError(0xdeadbeef); ret = GetTokenInformation(token, TokenType, &type, sizeof(type), &needed); ok(ret, "GetTokenInformation error %d\n", GetLastError()); ok(needed == sizeof(type), "GetTokenInformation should return required buffer length\n"); ok(type == TokenPrimary || type == TokenImpersonation, "expected TokenPrimary or TokenImpersonation, got %d\n", type);
*token_type = type; if (type != TokenImpersonation) return FALSE;
needed = 0; SetLastError(0xdeadbeef); ret = GetTokenInformation(token, TokenImpersonationLevel, &sil, sizeof(sil), &needed); ok(ret, "GetTokenInformation error %d\n", GetLastError()); ok(needed == sizeof(sil), "GetTokenInformation should return required buffer length\n"); ok(sil == SecurityImpersonation, "expected SecurityImpersonation, got %d\n", sil);
needed = 0xdeadbeef; SetLastError(0xdeadbeef); ret = GetTokenInformation(token, TokenDefaultDacl, NULL, 0, &needed); ok(!ret, "GetTokenInformation should fail\n"); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); ok(needed != 0xdeadbeef, "GetTokenInformation should return required buffer length\n"); ok(needed > sizeof(TOKEN_DEFAULT_DACL), "GetTokenInformation returned empty default DACL\n");
needed = 0xdeadbeef; SetLastError(0xdeadbeef); ret = GetTokenInformation(token, TokenOwner, NULL, 0, &needed); ok(!ret, "GetTokenInformation should fail\n"); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); ok(needed != 0xdeadbeef, "GetTokenInformation should return required buffer length\n"); ok(needed > sizeof(TOKEN_OWNER), "GetTokenInformation returned empty token owner\n");
needed = 0xdeadbeef; SetLastError(0xdeadbeef); ret = GetTokenInformation(token, TokenPrimaryGroup, NULL, 0, &needed); ok(!ret, "GetTokenInformation should fail\n"); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); ok(needed != 0xdeadbeef, "GetTokenInformation should return required buffer length\n"); ok(needed > sizeof(TOKEN_PRIMARY_GROUP), "GetTokenInformation returned empty token primary group\n");
return TRUE;}
static void test_kernel_objects_security(void){ HANDLE token, process_token; DWORD ret, token_type;
ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE | TOKEN_QUERY, &process_token); ok(ret, "OpenProcessToken error %d\n", GetLastError());
ret = validate_impersonation_token(process_token, &token_type); ok(token_type == TokenPrimary, "expected TokenPrimary, got %d\n", token_type); ok(!ret, "access token should not be an impersonation token\n");
ret = DuplicateToken(process_token, SecurityImpersonation, &token); ok(ret, "DuplicateToken error %d\n", GetLastError());
ret = validate_impersonation_token(token, &token_type); ok(ret, "access token should be a valid impersonation token\n"); ok(token_type == TokenImpersonation, "expected TokenImpersonation, got %d\n", token_type);
test_mutex_security(token); test_event_security(token); test_named_pipe_security(token); test_semaphore_security(token); test_file_security(token); test_filemap_security(); test_thread_security(); test_process_access(); /* FIXME: test other kernel object types */
CloseHandle(process_token); CloseHandle(token);}
static void test_TokenIntegrityLevel(void){ TOKEN_MANDATORY_LABEL *tml; BYTE buffer[64]; /* using max. 28 byte in win7 x64 */ HANDLE token; DWORD size; DWORD res; static SID medium_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, {SECURITY_MANDATORY_HIGH_RID}}; static SID high_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, {SECURITY_MANDATORY_MEDIUM_RID}};
SetLastError(0xdeadbeef); res = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token); ok(res, "got %d with %d (expected TRUE)\n", res, GetLastError());
SetLastError(0xdeadbeef); res = GetTokenInformation(token, TokenIntegrityLevel, buffer, sizeof(buffer), &size);
/* not supported before Vista */ if (!res && ((GetLastError() == ERROR_INVALID_PARAMETER) || GetLastError() == ERROR_INVALID_FUNCTION)) { win_skip("TokenIntegrityLevel not supported\n"); CloseHandle(token); return; }
ok(res, "got %u with %u (expected TRUE)\n", res, GetLastError()); if (!res) { CloseHandle(token); return; }
tml = (TOKEN_MANDATORY_LABEL*) buffer; ok(tml->Label.Attributes == (SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED), "got 0x%x (expected 0x%x)\n", tml->Label.Attributes, (SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED));
ok(EqualSid(tml->Label.Sid, &medium_level) || EqualSid(tml->Label.Sid, &high_level), "got %s (expected %s or %s)\n", debugstr_sid(tml->Label.Sid), debugstr_sid(&medium_level), debugstr_sid(&high_level));
CloseHandle(token);}
static void test_default_dacl_owner_sid(void){ HANDLE handle; BOOL ret, defaulted, present, found; DWORD size, index; SECURITY_DESCRIPTOR *sd; SECURITY_ATTRIBUTES sa; PSID owner; ACL *dacl; ACCESS_ALLOWED_ACE *ace;
sd = HeapAlloc( GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH ); ret = InitializeSecurityDescriptor( sd, SECURITY_DESCRIPTOR_REVISION ); ok( ret, "error %u\n", GetLastError() );
sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = sd; sa.bInheritHandle = FALSE; handle = CreateEventA( &sa, TRUE, TRUE, "test_event" ); ok( handle != NULL, "error %u\n", GetLastError() );
size = 0; ret = GetKernelObjectSecurity( handle, OWNER_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, NULL, 0, &size ); ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "error %u\n", GetLastError() );
sd = HeapAlloc( GetProcessHeap(), 0, size ); ret = GetKernelObjectSecurity( handle, OWNER_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, sd, size, &size ); ok( ret, "error %u\n", GetLastError() );
owner = (void *)0xdeadbeef; defaulted = TRUE; ret = GetSecurityDescriptorOwner( sd, &owner, &defaulted ); ok( ret, "error %u\n", GetLastError() ); ok( owner != (void *)0xdeadbeef, "owner not set\n" ); ok( !defaulted, "owner defaulted\n" );
dacl = (void *)0xdeadbeef; present = FALSE; defaulted = TRUE; ret = GetSecurityDescriptorDacl( sd, &present, &dacl, &defaulted ); ok( ret, "error %u\n", GetLastError() ); ok( present, "dacl not present\n" ); ok( dacl != (void *)0xdeadbeef, "dacl not set\n" ); ok( !defaulted, "dacl defaulted\n" );
index = 0; found = FALSE; while (pGetAce( dacl, index++, (void **)&ace )) { if (EqualSid( &ace->SidStart, owner )) found = TRUE; } ok( found, "owner sid not found in dacl\n" );
HeapFree( GetProcessHeap(), 0, sa.lpSecurityDescriptor ); HeapFree( GetProcessHeap(), 0, sd ); CloseHandle( handle );}
static void test_AdjustTokenPrivileges(void){ TOKEN_PRIVILEGES tp; HANDLE token; DWORD len; LUID luid; BOOL ret;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) return;
if (!LookupPrivilegeValueA(NULL, SE_BACKUP_NAME, &luid)) { CloseHandle(token); return; }
tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
len = 0xdeadbeef; ret = AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, &len); ok(ret, "got %d\n", ret); ok(len == 0xdeadbeef, "got length %d\n", len);
/* revert */ tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = 0; ret = AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL); ok(ret, "got %d\n", ret);
CloseHandle(token);}
static void test_AddAce(void){ static SID const sidWorld = { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY} , { SECURITY_WORLD_RID } };
char acl_buf[1024], ace_buf[256]; ACCESS_ALLOWED_ACE *ace = (ACCESS_ALLOWED_ACE*)ace_buf; PACL acl = (PACL)acl_buf; BOOL ret;
memset(ace, 0, sizeof(ace_buf)); ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; ace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD)+sizeof(SID); memcpy(&ace->SidStart, &sidWorld, sizeof(sidWorld));
ret = InitializeAcl(acl, sizeof(acl_buf), ACL_REVISION2); ok(ret, "InitializeAcl failed: %d\n", GetLastError());
ret = AddAce(acl, ACL_REVISION1, MAXDWORD, ace, ace->Header.AceSize); ok(ret, "AddAce failed: %d\n", GetLastError()); ret = AddAce(acl, ACL_REVISION2, MAXDWORD, ace, ace->Header.AceSize); ok(ret, "AddAce failed: %d\n", GetLastError()); ret = AddAce(acl, ACL_REVISION3, MAXDWORD, ace, ace->Header.AceSize); ok(ret, "AddAce failed: %d\n", GetLastError()); ok(acl->AclRevision == ACL_REVISION3, "acl->AclRevision = %d\n", acl->AclRevision); ret = AddAce(acl, ACL_REVISION4, MAXDWORD, ace, ace->Header.AceSize); ok(ret, "AddAce failed: %d\n", GetLastError()); ok(acl->AclRevision == ACL_REVISION4, "acl->AclRevision = %d\n", acl->AclRevision); ret = AddAce(acl, ACL_REVISION1, MAXDWORD, ace, ace->Header.AceSize); ok(ret, "AddAce failed: %d\n", GetLastError()); ok(acl->AclRevision == ACL_REVISION4, "acl->AclRevision = %d\n", acl->AclRevision); ret = AddAce(acl, ACL_REVISION2, MAXDWORD, ace, ace->Header.AceSize); ok(ret, "AddAce failed: %d\n", GetLastError());
ret = AddAce(acl, MIN_ACL_REVISION-1, MAXDWORD, ace, ace->Header.AceSize); ok(ret, "AddAce failed: %d\n", GetLastError()); /* next test succeededs but corrupts ACL */ ret = AddAce(acl, MAX_ACL_REVISION+1, MAXDWORD, ace, ace->Header.AceSize); ok(ret, "AddAce failed: %d\n", GetLastError()); ok(acl->AclRevision == MAX_ACL_REVISION+1, "acl->AclRevision = %d\n", acl->AclRevision); SetLastError(0xdeadbeef); ret = AddAce(acl, ACL_REVISION1, MAXDWORD, ace, ace->Header.AceSize); ok(!ret, "AddAce succeeded\n"); ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError() = %d\n", GetLastError());}
static void test_AddMandatoryAce(void){ static SID low_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, {SECURITY_MANDATORY_LOW_RID}}; static SID medium_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, {SECURITY_MANDATORY_MEDIUM_RID}}; static SID_IDENTIFIER_AUTHORITY sia_world = {SECURITY_WORLD_SID_AUTHORITY}; char buffer_sd[SECURITY_DESCRIPTOR_MIN_LENGTH]; SECURITY_DESCRIPTOR *sd2, *sd = (SECURITY_DESCRIPTOR *)&buffer_sd; BOOL defaulted, present, ret, found, found2; ACL_SIZE_INFORMATION acl_size_info; SYSTEM_MANDATORY_LABEL_ACE *ace; char buffer_acl[256]; ACL *acl = (ACL *)&buffer_acl; SECURITY_ATTRIBUTES sa; DWORD index, size; HANDLE handle; SID *everyone; ACL *sacl;
if (!pAddMandatoryAce) { win_skip("AddMandatoryAce not supported, skipping test\n"); return; }
ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION); ok(ret, "InitializeSecurityDescriptor failed with error %u\n", GetLastError());
sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = sd; sa.bInheritHandle = FALSE;
handle = CreateEventA(&sa, TRUE, TRUE, "test_event"); ok(handle != NULL, "CreateEventA failed with error %u\n", GetLastError());
ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
sd2 = HeapAlloc(GetProcessHeap(), 0, size); ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size); ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
sacl = (void *)0xdeadbeef; present = TRUE; ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted); ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); ok(!present, "SACL is present\n"); ok(sacl == (void *)0xdeadbeef, "SACL is set\n");
HeapFree(GetProcessHeap(), 0, sd2); CloseHandle(handle);
memset(buffer_acl, 0, sizeof(buffer_acl)); ret = InitializeAcl(acl, 256, ACL_REVISION); ok(ret, "InitializeAcl failed with %u\n", GetLastError());
SetLastError(0xdeadbeef); ret = pAddMandatoryAce(acl, ACL_REVISION, 0, 0x1234, &low_level); ok(!ret, "AddMandatoryAce succeeded\n"); ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER got %u\n", GetLastError());
ret = pAddMandatoryAce(acl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, &low_level); ok(ret, "AddMandatoryAce failed with %u\n", GetLastError());
index = 0; found = FALSE; while (pGetAce(acl, index++, (void **)&ace)) { if (ace->Header.AceType != SYSTEM_MANDATORY_LABEL_ACE_TYPE) continue; ok(ace->Header.AceFlags == 0, "Expected flags 0, got %x\n", ace->Header.AceFlags); ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, "Expected mask SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, got %x\n", ace->Mask); ok(EqualSid(&ace->SidStart, &low_level), "Expected low integrity level\n"); found = TRUE; } ok(found, "Could not find mandatory label ace\n");
ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE); ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError());
handle = CreateEventA(&sa, TRUE, TRUE, "test_event"); ok(handle != NULL, "CreateEventA failed with error %u\n", GetLastError());
ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
sd2 = HeapAlloc(GetProcessHeap(), 0, size); ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size); ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
sacl = (void *)0xdeadbeef; present = FALSE; defaulted = TRUE; ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted); ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); ok(present, "SACL not present\n"); ok(sacl != (void *)0xdeadbeef, "SACL not set\n"); ok(!defaulted, "SACL defaulted\n"); ret = pGetAclInformation(sacl, &acl_size_info, sizeof(acl_size_info), AclSizeInformation); ok(ret, "GetAclInformation failed with error %u\n", GetLastError()); ok(acl_size_info.AceCount == 1, "SACL contains an unexpected ACE count %u\n", acl_size_info.AceCount);
ret = pGetAce(sacl, 0, (void **)&ace); ok(ret, "GetAce failed with error %u\n", GetLastError()); ok (ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, "Unexpected ACE type %#x\n", ace->Header.AceType); ok(!ace->Header.AceFlags, "Unexpected ACE flags %#x\n", ace->Header.AceFlags); ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, "Unexpected ACE mask %#x\n", ace->Mask); ok(EqualSid(&ace->SidStart, &low_level), "Expected low integrity level\n");
HeapFree(GetProcessHeap(), 0, sd2);
ret = pAddMandatoryAce(acl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP, &medium_level); ok(ret, "AddMandatoryAce failed with error %u\n", GetLastError());
ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd); ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError());
ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
sd2 = HeapAlloc(GetProcessHeap(), 0, size); ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size); ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
sacl = (void *)0xdeadbeef; present = FALSE; defaulted = TRUE; ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted); ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); ok(present, "SACL not present\n"); ok(sacl != (void *)0xdeadbeef, "SACL not set\n"); ok(sacl->AceCount == 2, "Expected 2 ACEs, got %d\n", sacl->AceCount); ok(!defaulted, "SACL defaulted\n");
index = 0; found = found2 = FALSE; while (pGetAce(sacl, index++, (void **)&ace)) { if (ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE) { if (EqualSid(&ace->SidStart, &low_level)) { found = TRUE; ok(!ace->Header.AceFlags, "Expected 0 as flags, got %#x\n", ace->Header.AceFlags); ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, "Expected SYSTEM_MANDATORY_LABEL_NO_WRITE_UP as mask, got %#x\n", ace->Mask); } if (EqualSid(&ace->SidStart, &medium_level)) { found2 = TRUE; ok(!ace->Header.AceFlags, "Expected 0 as flags, got %#x\n", ace->Header.AceFlags); ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP, "Expected SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP as mask, got %#x\n", ace->Mask); } } } ok(found, "Could not find low mandatory label\n"); ok(found2, "Could not find medium mandatory label\n");
HeapFree(GetProcessHeap(), 0, sd2);
ret = SetSecurityDescriptorSacl(sd, FALSE, NULL, FALSE); ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError());
ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd); ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError());
ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
sd2 = HeapAlloc(GetProcessHeap(), 0, size); ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size); ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
sacl = (void *)0xdeadbeef; present = FALSE; defaulted = TRUE; ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted); ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); ok(present, "SACL not present\n"); ok(sacl && sacl != (void *)0xdeadbeef, "SACL not set\n"); ok(!defaulted, "SACL defaulted\n"); ok(!sacl->AceCount, "SACL contains an unexpected ACE count %u\n", sacl->AceCount);
HeapFree(GetProcessHeap(), 0, sd2);
ret = InitializeAcl(acl, 256, ACL_REVISION); ok(ret, "InitializeAcl failed with error %u\n", GetLastError());
ret = pAddMandatoryAce(acl, ACL_REVISION3, 0, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP, &medium_level); ok(ret, "AddMandatoryAce failed with error %u\n", GetLastError());
ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE); ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError());
ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd); ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError());
ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
sd2 = HeapAlloc(GetProcessHeap(), 0, size); ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size); ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
sacl = (void *)0xdeadbeef; present = FALSE; defaulted = TRUE; ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted); ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); ok(present, "SACL not present\n"); ok(sacl != (void *)0xdeadbeef, "SACL not set\n"); ok(sacl->AclRevision == ACL_REVISION3, "Expected revision 3, got %d\n", sacl->AclRevision); ok(!defaulted, "SACL defaulted\n");
HeapFree(GetProcessHeap(), 0, sd2);
ret = InitializeAcl(acl, 256, ACL_REVISION); ok(ret, "InitializeAcl failed with error %u\n", GetLastError());
ret = AllocateAndInitializeSid(&sia_world, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, (void **)&everyone); ok(ret, "AllocateAndInitializeSid failed with error %u\n", GetLastError());
ret = AddAccessAllowedAce(acl, ACL_REVISION, KEY_READ, everyone); ok(ret, "AddAccessAllowedAce failed with error %u\n", GetLastError());
ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE); ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError());
ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd); ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError());
ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
sd2 = HeapAlloc(GetProcessHeap(), 0, size); ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size); ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
sacl = (void *)0xdeadbeef; present = FALSE; defaulted = TRUE; ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted); ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); ok(present, "SACL not present\n"); ok(sacl && sacl != (void *)0xdeadbeef, "SACL not set\n"); ok(!defaulted, "SACL defaulted\n"); ok(!sacl->AceCount, "SACL contains an unexpected ACE count %u\n", sacl->AceCount);
FreeSid(everyone); HeapFree(GetProcessHeap(), 0, sd2); CloseHandle(handle);}
static void test_system_security_access(void){ static const WCHAR testkeyW[] = {'S','O','F','T','W','A','R','E','\\','W','i','n','e','\\','S','A','C','L','t','e','s','t',0}; LONG res; HKEY hkey; PSECURITY_DESCRIPTOR sd; ACL *sacl; DWORD err, len = 128; TOKEN_PRIVILEGES priv, *priv_prev; HANDLE token; LUID luid; BOOL ret;
if (!OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &token )) return; if (!LookupPrivilegeValueA( NULL, SE_SECURITY_NAME, &luid )) { CloseHandle( token ); return; }
/* ACCESS_SYSTEM_SECURITY requires special privilege */ res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ|ACCESS_SYSTEM_SECURITY, NULL, &hkey, NULL ); if (res == ERROR_ACCESS_DENIED) { skip( "unprivileged user\n" ); CloseHandle( token ); return; } todo_wine ok( res == ERROR_PRIVILEGE_NOT_HELD, "got %d\n", res );
priv.PrivilegeCount = 1; priv.Privileges[0].Luid = luid; priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
priv_prev = HeapAlloc( GetProcessHeap(), 0, len ); ret = AdjustTokenPrivileges( token, FALSE, &priv, len, priv_prev, &len ); ok( ret, "got %u\n", GetLastError());
res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ|ACCESS_SYSTEM_SECURITY, NULL, &hkey, NULL ); if (res == ERROR_PRIVILEGE_NOT_HELD) { win_skip( "privilege not held\n" ); HeapFree( GetProcessHeap(), 0, priv_prev ); CloseHandle( token ); return; } ok( !res, "got %d\n", res );
/* restore privileges */ ret = AdjustTokenPrivileges( token, FALSE, priv_prev, 0, NULL, NULL ); ok( ret, "got %u\n", GetLastError() ); HeapFree( GetProcessHeap(), 0, priv_prev );
/* privilege is checked on access */ err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd ); todo_wine ok( err == ERROR_PRIVILEGE_NOT_HELD, "got %u\n", err ); if (err == ERROR_SUCCESS) LocalFree( sd );
priv.PrivilegeCount = 1; priv.Privileges[0].Luid = luid; priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
priv_prev = HeapAlloc( GetProcessHeap(), 0, len ); ret = AdjustTokenPrivileges( token, FALSE, &priv, len, priv_prev, &len ); ok( ret, "got %u\n", GetLastError());
err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd ); ok( err == ERROR_SUCCESS, "got %u\n", err ); RegCloseKey( hkey ); LocalFree( sd );
/* handle created without ACCESS_SYSTEM_SECURITY, privilege held */ res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ, NULL, &hkey, NULL ); ok( res == ERROR_SUCCESS, "got %d\n", res );
sd = NULL; err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd ); todo_wine ok( err == ERROR_SUCCESS, "got %u\n", err ); RegCloseKey( hkey ); LocalFree( sd );
/* restore privileges */ ret = AdjustTokenPrivileges( token, FALSE, priv_prev, 0, NULL, NULL ); ok( ret, "got %u\n", GetLastError() ); HeapFree( GetProcessHeap(), 0, priv_prev );
/* handle created without ACCESS_SYSTEM_SECURITY, privilege not held */ res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ, NULL, &hkey, NULL ); ok( res == ERROR_SUCCESS, "got %d\n", res );
err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd ); todo_wine ok( err == ERROR_PRIVILEGE_NOT_HELD, "got %u\n", err ); RegCloseKey( hkey );
res = RegDeleteKeyW( HKEY_LOCAL_MACHINE, testkeyW ); ok( !res, "got %d\n", res ); CloseHandle( token );}
static void test_GetWindowsAccountDomainSid(void){ char *user, buffer1[SECURITY_MAX_SID_SIZE], buffer2[SECURITY_MAX_SID_SIZE]; SID_IDENTIFIER_AUTHORITY domain_ident = { SECURITY_NT_AUTHORITY }; PSID domain_sid = (PSID *)&buffer1; PSID domain_sid2 = (PSID *)&buffer2; DWORD sid_size; PSID user_sid; HANDLE token; BOOL bret = TRUE; int i;
if (!pGetWindowsAccountDomainSid) { win_skip("GetWindowsAccountDomainSid not available\n"); return; }
if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token)) { if (GetLastError() != ERROR_NO_TOKEN) bret = FALSE; else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) bret = FALSE; } if (!bret) { win_skip("Failed to get current user token\n"); return; }
bret = GetTokenInformation(token, TokenUser, NULL, 0, &sid_size); ok(!bret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError()); user = HeapAlloc(GetProcessHeap(), 0, sid_size); bret = GetTokenInformation(token, TokenUser, user, sid_size, &sid_size); ok(bret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError()); CloseHandle(token); user_sid = ((TOKEN_USER *)user)->User.Sid;
SetLastError(0xdeadbeef); bret = pGetWindowsAccountDomainSid(0, 0, 0); ok(!bret, "GetWindowsAccountDomainSid succeeded\n"); ok(GetLastError() == ERROR_INVALID_SID, "expected ERROR_INVALID_SID, got %d\n", GetLastError());
SetLastError(0xdeadbeef); bret = pGetWindowsAccountDomainSid(user_sid, 0, 0); ok(!bret, "GetWindowsAccountDomainSid succeeded\n"); ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
sid_size = SECURITY_MAX_SID_SIZE; SetLastError(0xdeadbeef); bret = pGetWindowsAccountDomainSid(user_sid, 0, &sid_size); ok(!bret, "GetWindowsAccountDomainSid succeeded\n"); ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); ok(sid_size == GetSidLengthRequired(4), "expected size %d, got %d\n", GetSidLengthRequired(4), sid_size);
SetLastError(0xdeadbeef); bret = pGetWindowsAccountDomainSid(user_sid, domain_sid, 0); ok(!bret, "GetWindowsAccountDomainSid succeeded\n"); ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
sid_size = 1; SetLastError(0xdeadbeef); bret = pGetWindowsAccountDomainSid(user_sid, domain_sid, &sid_size); ok(!bret, "GetWindowsAccountDomainSid succeeded\n"); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); ok(sid_size == GetSidLengthRequired(4), "expected size %d, got %d\n", GetSidLengthRequired(4), sid_size);
sid_size = SECURITY_MAX_SID_SIZE; bret = pGetWindowsAccountDomainSid(user_sid, domain_sid, &sid_size); ok(bret, "GetWindowsAccountDomainSid failed with error %d\n", GetLastError()); ok(sid_size == GetSidLengthRequired(4), "expected size %d, got %d\n", GetSidLengthRequired(4), sid_size); InitializeSid(domain_sid2, &domain_ident, 4); for (i = 0; i < 4; i++) *GetSidSubAuthority(domain_sid2, i) = *GetSidSubAuthority(user_sid, i); ok(EqualSid(domain_sid, domain_sid2), "unexpected domain sid %s != %s\n", debugstr_sid(domain_sid), debugstr_sid(domain_sid2));
HeapFree(GetProcessHeap(), 0, user);}
static void test_GetSidIdentifierAuthority(void){ char buffer[SECURITY_MAX_SID_SIZE]; PSID authority_sid = (PSID *)buffer; PSID_IDENTIFIER_AUTHORITY id; BOOL ret;
if (!pGetSidIdentifierAuthority) { win_skip("GetSidIdentifierAuthority not available\n"); return; }
memset(buffer, 0xcc, sizeof(buffer)); ret = IsValidSid(authority_sid); ok(!ret, "expected FALSE, got %u\n", ret);
SetLastError(0xdeadbeef); id = GetSidIdentifierAuthority(authority_sid); ok(id != NULL, "got NULL pointer as identifier authority\n"); ok(GetLastError() == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", GetLastError());
SetLastError(0xdeadbeef); id = GetSidIdentifierAuthority(NULL); ok(id != NULL, "got NULL pointer as identifier authority\n"); ok(GetLastError() == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", GetLastError());}
static void test_pseudo_tokens(void){ TOKEN_STATISTICS statistics1, statistics2; HANDLE token; DWORD retlen; BOOL ret;
ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token); ok(ret, "OpenProcessToken failed with error %u\n", GetLastError()); memset(&statistics1, 0x11, sizeof(statistics1)); ret = GetTokenInformation(token, TokenStatistics, &statistics1, sizeof(statistics1), &retlen); ok(ret, "GetTokenInformation failed with %u\n", GetLastError()); CloseHandle(token);
/* test GetCurrentProcessToken() */ SetLastError(0xdeadbeef); memset(&statistics2, 0x22, sizeof(statistics2)); ret = GetTokenInformation(GetCurrentProcessToken(), TokenStatistics, &statistics2, sizeof(statistics2), &retlen); ok(ret || broken(GetLastError() == ERROR_INVALID_HANDLE), "GetTokenInformation failed with %u\n", GetLastError()); if (ret) ok(!memcmp(&statistics1, &statistics2, sizeof(statistics1)), "Token statistics do not match\n"); else win_skip("CurrentProcessToken not supported, skipping test\n");
/* test GetCurrentThreadEffectiveToken() */ SetLastError(0xdeadbeef); memset(&statistics2, 0x22, sizeof(statistics2)); ret = GetTokenInformation(GetCurrentThreadEffectiveToken(), TokenStatistics, &statistics2, sizeof(statistics2), &retlen); ok(ret || broken(GetLastError() == ERROR_INVALID_HANDLE), "GetTokenInformation failed with %u\n", GetLastError()); if (ret) ok(!memcmp(&statistics1, &statistics2, sizeof(statistics1)), "Token statistics do not match\n"); else win_skip("CurrentThreadEffectiveToken not supported, skipping test\n");
SetLastError(0xdeadbeef); ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &token); ok(!ret, "OpenThreadToken should have failed\n"); ok(GetLastError() == ERROR_NO_TOKEN, "Expected ERROR_NO_TOKEN, got %u\n", GetLastError());
/* test GetCurrentThreadToken() */ SetLastError(0xdeadbeef); ret = GetTokenInformation(GetCurrentThreadToken(), TokenStatistics, &statistics2, sizeof(statistics2), &retlen); todo_wine ok(GetLastError() == ERROR_NO_TOKEN || broken(GetLastError() == ERROR_INVALID_HANDLE), "Expected ERROR_NO_TOKEN, got %u\n", GetLastError());}
static void test_maximum_allowed(void){ HANDLE (WINAPI *pCreateEventExA)(SECURITY_ATTRIBUTES *, LPCSTR, DWORD, DWORD); char buffer_sd[SECURITY_DESCRIPTOR_MIN_LENGTH], buffer_acl[256]; SECURITY_DESCRIPTOR *sd = (SECURITY_DESCRIPTOR *)&buffer_sd; SECURITY_ATTRIBUTES sa; ACL *acl = (ACL *)&buffer_acl; HMODULE hkernel32 = GetModuleHandleA("kernel32.dll"); ACCESS_MASK mask; HANDLE handle; BOOL ret;
pCreateEventExA = (void *)GetProcAddress(hkernel32, "CreateEventExA"); if (!pCreateEventExA) { win_skip("CreateEventExA is not available\n"); return; }
ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION); ok(ret, "InitializeSecurityDescriptor failed with %u\n", GetLastError()); memset(buffer_acl, 0, sizeof(buffer_acl)); ret = InitializeAcl(acl, 256, ACL_REVISION); ok(ret, "InitializeAcl failed with %u\n", GetLastError()); ret = SetSecurityDescriptorDacl(sd, TRUE, acl, FALSE); ok(ret, "SetSecurityDescriptorDacl failed with %u\n", GetLastError());
sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = sd; sa.bInheritHandle = FALSE;
handle = pCreateEventExA(&sa, NULL, 0, MAXIMUM_ALLOWED | 0x4); ok(handle != NULL, "CreateEventExA failed with error %u\n", GetLastError()); mask = get_obj_access(handle); ok(mask == EVENT_ALL_ACCESS, "Expected %x, got %x\n", EVENT_ALL_ACCESS, mask); CloseHandle(handle);}
static void test_token_label(void){ static SID medium_sid = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, {SECURITY_MANDATORY_MEDIUM_RID}}; static SID high_sid = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, {SECURITY_MANDATORY_HIGH_RID}}; SECURITY_DESCRIPTOR_CONTROL control; SYSTEM_MANDATORY_LABEL_ACE *ace; BOOL ret, present, defaulted; SECURITY_DESCRIPTOR *sd; ACL *sacl = NULL, *dacl; DWORD size, revision; HANDLE token; char *str; SID *sid;
ret = OpenProcessToken(GetCurrentProcess(), READ_CONTROL | WRITE_OWNER, &token); ok(ret, "OpenProcessToken failed with error %u\n", GetLastError());
ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
sd = HeapAlloc(GetProcessHeap(), 0, size); ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd, size, &size); ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
ret = GetSecurityDescriptorControl(sd, &control, &revision); ok(ret, "GetSecurityDescriptorControl failed with error %u\n", GetLastError()); todo_wine ok(control == (SE_SELF_RELATIVE | SE_SACL_AUTO_INHERITED | SE_SACL_PRESENT) || broken(control == SE_SELF_RELATIVE) /* WinXP, Win2003 */, "Unexpected security descriptor control %#x\n", control); ok(revision == 1, "Unexpected security descriptor revision %u\n", revision);
sid = (void *)0xdeadbeef; defaulted = TRUE; ret = GetSecurityDescriptorOwner(sd, (void **)&sid, &defaulted); ok(ret, "GetSecurityDescriptorOwner failed with error %u\n", GetLastError()); ok(!sid, "Owner present\n"); ok(!defaulted, "Owner defaulted\n");
sid = (void *)0xdeadbeef; defaulted = TRUE; ret = GetSecurityDescriptorGroup(sd, (void **)&sid, &defaulted); ok(ret, "GetSecurityDescriptorGroup failed with error %u\n", GetLastError()); ok(!sid, "Group present\n"); ok(!defaulted, "Group defaulted\n");
ret = GetSecurityDescriptorSacl(sd, &present, &sacl, &defaulted); ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); ok(present || broken(!present) /* WinXP, Win2003 */, "No SACL in the security descriptor\n"); ok(sacl || broken(!sacl) /* WinXP, Win2003 */, "NULL SACL in the security descriptor\n");
if (present) { ok(!defaulted, "SACL defaulted\n"); ok(sacl->AceCount == 1, "SACL contains an unexpected ACE count %u\n", sacl->AceCount);
ret = pGetAce(sacl, 0, (void **)&ace); ok(ret, "GetAce failed with error %u\n", GetLastError());
ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, "Unexpected ACE type %#x\n", ace->Header.AceType); ok(!ace->Header.AceFlags, "Unexpected ACE flags %#x\n", ace->Header.AceFlags); ok(ace->Header.AceSize, "Unexpected ACE size %u\n", ace->Header.AceSize); ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, "Unexpected ACE mask %#x\n", ace->Mask);
sid = (SID *)&ace->SidStart; ConvertSidToStringSidA(sid, &str); ok(EqualSid(sid, &medium_sid) || EqualSid(sid, &high_sid), "Got unexpected SID %s\n", str); LocalFree(str); }
ret = GetSecurityDescriptorDacl(sd, &present, &dacl, &defaulted); ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError()); todo_wine ok(!present, "DACL present\n");
HeapFree(GetProcessHeap(), 0, sd); CloseHandle(token);}
static void test_token_security_descriptor(void){ static SID low_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, {SECURITY_MANDATORY_LOW_RID}}; static SID medium_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, {SECURITY_MANDATORY_MEDIUM_RID}}; static SID high_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, {SECURITY_MANDATORY_HIGH_RID}}; char buffer_sd[SECURITY_DESCRIPTOR_MIN_LENGTH]; SECURITY_DESCRIPTOR *sd = (SECURITY_DESCRIPTOR *)&buffer_sd, *sd2, *sd3; char buffer_acl[256], buffer[MAX_PATH]; ACL *acl = (ACL *)&buffer_acl, *acl2, *acl_child, *sacl; BOOL defaulted, present, ret, found; HANDLE token, token2, token3, token4, token5, token6; EXPLICIT_ACCESSW exp_access; TOKEN_MANDATORY_LABEL *tml; BYTE buffer_integrity[64]; PROCESS_INFORMATION info; DWORD size, index, retd; ACCESS_ALLOWED_ACE *ace; SECURITY_ATTRIBUTES sa; STARTUPINFOA startup; PSID psid;
if (!pDuplicateTokenEx || !pConvertStringSidToSidA || !pAddAccessAllowedAceEx || !pGetAce || !pSetEntriesInAclW) { win_skip("Some functions not available\n"); return; }
/* Test whether we can create tokens with security descriptors */ ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token); ok(ret, "OpenProcessToken failed with error %u\n", GetLastError());
ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION); ok(ret, "InitializeSecurityDescriptor failed with error %u\n", GetLastError());
memset(buffer_acl, 0, sizeof(buffer_acl)); ret = InitializeAcl(acl, 256, ACL_REVISION); ok(ret, "InitializeAcl failed with error %u\n", GetLastError());
ret = pConvertStringSidToSidA("S-1-5-6", &psid); ok(ret, "ConvertStringSidToSidA failed with error %u\n", GetLastError());
ret = pAddAccessAllowedAceEx(acl, ACL_REVISION, NO_PROPAGATE_INHERIT_ACE, GENERIC_ALL, psid); ok(ret, "AddAccessAllowedAceEx failed with error %u\n", GetLastError());
ret = SetSecurityDescriptorDacl(sd, TRUE, acl, FALSE); ok(ret, "SetSecurityDescriptorDacl failed with error %u\n", GetLastError());
sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = sd; sa.bInheritHandle = FALSE;
ret = pDuplicateTokenEx(token, MAXIMUM_ALLOWED, &sa, SecurityImpersonation, TokenImpersonation, &token2); ok(ret, "DuplicateTokenEx failed with error %u\n", GetLastError());
ret = GetKernelObjectSecurity(token2, DACL_SECURITY_INFORMATION, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
sd2 = HeapAlloc(GetProcessHeap(), 0, size); ret = GetKernelObjectSecurity(token2, DACL_SECURITY_INFORMATION, sd2, size, &size); ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
acl2 = (void *)0xdeadbeef; present = FALSE; defaulted = TRUE; ret = GetSecurityDescriptorDacl(sd2, &present, &acl2, &defaulted); ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError()); ok(present, "acl2 not present\n"); ok(acl2 != (void *)0xdeadbeef, "acl2 not set\n"); ok(acl2->AceCount == 1, "Expected 1 ACE, got %d\n", acl2->AceCount); ok(!defaulted, "acl2 defaulted\n");
ret = pGetAce(acl2, 0, (void **)&ace); ok(ret, "GetAce failed with error %u\n", GetLastError()); ok(ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE, "Unexpected ACE type %#x\n", ace->Header.AceType); ok(EqualSid(&ace->SidStart, psid), "Expected access allowed ACE\n"); ok(ace->Header.AceFlags == NO_PROPAGATE_INHERIT_ACE, "Expected NO_PROPAGATE_INHERIT_ACE as flags, got %x\n", ace->Header.AceFlags);
HeapFree(GetProcessHeap(), 0, sd2);
/* Duplicate token without security attributes. * Tokens do not inherit the security descriptor in DuplicateToken. */ ret = pDuplicateTokenEx(token2, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenImpersonation, &token3); ok(ret, "DuplicateTokenEx failed with error %u\n", GetLastError());
ret = GetKernelObjectSecurity(token3, DACL_SECURITY_INFORMATION, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
sd2 = HeapAlloc(GetProcessHeap(), 0, size); ret = GetKernelObjectSecurity(token3, DACL_SECURITY_INFORMATION, sd2, size, &size); ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
acl2 = (void *)0xdeadbeef; present = FALSE; defaulted = TRUE; ret = GetSecurityDescriptorDacl(sd2, &present, &acl2, &defaulted); ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError()); ok(present, "DACL not present\n");
if (present) { ok(acl2 != (void *)0xdeadbeef, "DACL not set\n"); ok(!defaulted, "DACL defaulted\n");
index = 0; found = FALSE; while (pGetAce(acl2, index++, (void **)&ace)) { if (ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE && EqualSid(&ace->SidStart, psid)) found = TRUE; } ok(!found, "Access allowed ACE was inherited\n"); }
HeapFree(GetProcessHeap(), 0, sd2);
/* When creating a child process, the process does inherit the token of * the parent but not the DACL of the token */ ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
sd2 = HeapAlloc(GetProcessHeap(), 0, size); ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, sd2, size, &size); ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
acl2 = (void *)0xdeadbeef; present = FALSE; defaulted = TRUE; ret = GetSecurityDescriptorDacl(sd2, &present, &acl2, &defaulted); ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError()); ok(present, "DACL not present\n"); ok(acl2 != (void *)0xdeadbeef, "DACL not set\n"); ok(!defaulted, "DACL defaulted\n");
exp_access.grfAccessPermissions = GENERIC_ALL; exp_access.grfAccessMode = GRANT_ACCESS; exp_access.grfInheritance = NO_PROPAGATE_INHERIT_ACE; exp_access.Trustee.pMultipleTrustee = NULL; exp_access.Trustee.TrusteeForm = TRUSTEE_IS_SID; exp_access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; exp_access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; exp_access.Trustee.ptstrName = (void*)psid;
retd = pSetEntriesInAclW(1, &exp_access, acl2, &acl_child); ok(retd == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", retd);
memset(sd, 0, sizeof(buffer_sd)); ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION); ok(ret, "InitializeSecurityDescriptor failed with error %u\n", GetLastError());
ret = SetSecurityDescriptorDacl(sd, TRUE, acl_child, FALSE); ok(ret, "SetSecurityDescriptorDacl failed with error %u\n", GetLastError());
ret = SetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, sd); ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError());
/* The security label is also not inherited */ if (pAddMandatoryAce) { memset(buffer_integrity, 0, sizeof(buffer_integrity)); ret = GetTokenInformation(token, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size); ok(ret, "GetTokenInformation failed with error %u\n", GetLastError()); tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity; ok(EqualSid(tml->Label.Sid, &medium_level) || EqualSid(tml->Label.Sid, &high_level), "Expected medium or high integrity level\n");
if (EqualSid(tml->Label.Sid, &high_level)) { DWORD process_id; HANDLE process; HWND shell;
/* This test tries to get a medium token and then impersonates this token. The * idea is to check whether the sd label of a newly created token depends on the * current active token or the integrity level of the newly created token. */
/* Steal process token of the explorer.exe process */ shell = GetShellWindow(); todo_wine ok(shell != NULL, "Failed to get shell window\n"); if (!shell) shell = GetDesktopWindow(); /* FIXME: Workaround for Wine */ ok(GetWindowThreadProcessId(shell, &process_id), "Failed to get process id of shell window: %u\n", GetLastError()); process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, process_id); ok(process != NULL, "Failed to open process: %u\n", GetLastError()); ok(OpenProcessToken(process, TOKEN_ALL_ACCESS, &token4), "Failed to open process token: %u\n", GetLastError()); CloseHandle(process);
/* Check TokenIntegrityLevel and LABEL_SECURITY_INFORMATION of explorer.exe token */ memset(buffer_integrity, 0, sizeof(buffer_integrity)); ret = GetTokenInformation(token4, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size); ok(ret, "GetTokenInformation failed with error %u\n", GetLastError()); tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity; ok(EqualSid(tml->Label.Sid, &medium_level), "Expected medium integrity level\n");
size = 0; ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, sd3, size, &size); ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
sacl = NULL; ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted); ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); ok(present, "No SACL in the security descriptor\n"); ok(sacl != NULL, "NULL SACL in the security descriptor\n");
if (sacl) { ret = pGetAce(sacl, 0, (void **)&ace); ok(ret, "GetAce failed with error %u\n", GetLastError()); ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, "Unexpected ACE type %#x\n", ace->Header.AceType); ok(EqualSid(&ace->SidStart, &medium_level), "Expected medium integrity level\n"); }
HeapFree(GetProcessHeap(), 0, sd3);
/* Start child process with the explorer.exe token */ memset(&startup, 0, sizeof(startup)); startup.cb = sizeof(startup); startup.dwFlags = STARTF_USESHOWWINDOW; startup.wShowWindow = SW_SHOWNORMAL;
sprintf(buffer, "%s tests/security.c test_token_sd_medium", myARGV[0]); ret = CreateProcessAsUserA(token4, NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info); ok(ret || GetLastError() == ERROR_PRIVILEGE_NOT_HELD, "CreateProcess failed with error %u\n", GetLastError()); if (ret) { winetest_wait_child_process(info.hProcess); CloseHandle(info.hProcess); CloseHandle(info.hThread); } else win_skip("Skipping test for creating process with medium level token\n");
ret = DuplicateTokenEx(token4, 0, NULL, SecurityImpersonation, TokenImpersonation, &token5); ok(ret, "DuplicateTokenEx failed with error %u\n", GetLastError()); ret = SetThreadToken(NULL, token5); ok(ret, "SetThreadToken failed with error %u\n", GetLastError()); CloseHandle(token4);
/* Restrict current process token while impersonating a medium integrity token */ ret = CreateRestrictedToken(token, 0, 0, NULL, 0, NULL, 0, NULL, &token6); ok(ret, "CreateRestrictedToken failed with error %u\n", GetLastError());
memset(buffer_integrity, 0, sizeof(buffer_integrity)); ret = GetTokenInformation(token6, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size); ok(ret, "GetTokenInformation failed with error %u\n", GetLastError()); tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity; ok(EqualSid(tml->Label.Sid, &high_level), "Expected high integrity level\n");
size = 0; ret = GetKernelObjectSecurity(token6, LABEL_SECURITY_INFORMATION, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); ret = GetKernelObjectSecurity(token6, LABEL_SECURITY_INFORMATION, sd3, size, &size); ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
sacl = NULL; ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted); ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); ok(present, "No SACL in the security descriptor\n"); ok(sacl != NULL, "NULL SACL in the security descriptor\n");
if (sacl) { ret = pGetAce(sacl, 0, (void **)&ace); ok(ret, "GetAce failed with error %u\n", GetLastError()); ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, "Unexpected ACE type %#x\n", ace->Header.AceType); ok(EqualSid(&ace->SidStart, &medium_level), "Expected medium integrity level\n"); }
HeapFree(GetProcessHeap(), 0, sd3); RevertToSelf(); CloseHandle(token5);
/* Start child process with the restricted token */ sprintf(buffer, "%s tests/security.c test_token_sd_restricted", myARGV[0]); ret = CreateProcessAsUserA(token6, NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info); ok(ret, "CreateProcess failed with error %u\n", GetLastError()); winetest_wait_child_process(info.hProcess); CloseHandle(info.hProcess); CloseHandle(info.hThread); CloseHandle(token6);
/* DuplicateTokenEx should assign security label even when SA points to empty SD */ memset(sd, 0, sizeof(buffer_sd)); ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION); ok(ret, "InitializeSecurityDescriptor failed with error %u\n", GetLastError());
sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = sd; sa.bInheritHandle = FALSE;
ret = DuplicateTokenEx(token, 0, &sa, 0, TokenPrimary, &token6); ok(ret, "DuplicateTokenEx failed with error %u\n", GetLastError());
size = 0; ret = GetKernelObjectSecurity(token6, LABEL_SECURITY_INFORMATION, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); ret = GetKernelObjectSecurity(token6, LABEL_SECURITY_INFORMATION, sd3, size, &size); ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
sacl = NULL; ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted); ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); ok(present, "No SACL in the security descriptor\n"); ok(sacl != NULL, "NULL SACL in the security descriptor\n");
if (sacl) { ret = pGetAce(sacl, 0, (void **)&ace); ok(ret, "GetAce failed with error %u\n", GetLastError()); ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, "Unexpected ACE type %#x\n", ace->Header.AceType); ok(EqualSid(&ace->SidStart, &high_level), "Expected high integrity level\n"); }
HeapFree(GetProcessHeap(), 0, sd3); CloseHandle(token6); } else skip("Skipping test, running without admin rights\n");
ret = InitializeAcl(acl, 256, ACL_REVISION); ok(ret, "InitializeAcl failed with error %u\n", GetLastError());
ret = pAddMandatoryAce(acl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, &low_level); ok(ret, "AddMandatoryAce failed with error %u\n", GetLastError());
memset(sd, 0, sizeof(buffer_sd)); ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION); ok(ret, "InitializeSecurityDescriptor failed with error %u\n", GetLastError());
ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE); ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError());
ret = SetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd); ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError());
/* changing the label of the security descriptor does not change the integrity level of the token itself */ memset(buffer_integrity, 0, sizeof(buffer_integrity)); ret = GetTokenInformation(token, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size); ok(ret, "GetTokenInformation failed with error %u\n", GetLastError()); tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity; ok(EqualSid(tml->Label.Sid, &medium_level) || EqualSid(tml->Label.Sid, &high_level), "Expected medium or high integrity level\n");
/* restricting / duplicating a token resets the mandatory sd label */ ret = CreateRestrictedToken(token, 0, 0, NULL, 0, NULL, 0, NULL, &token4); ok(ret, "CreateRestrictedToken failed with error %u\n", GetLastError());
memset(buffer_integrity, 0, sizeof(buffer_integrity)); ret = GetTokenInformation(token4, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size); ok(ret, "GetTokenInformation failed with error %u\n", GetLastError()); tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity; ok(EqualSid(tml->Label.Sid, &medium_level) || EqualSid(tml->Label.Sid, &high_level), "Expected medium or high integrity level\n");
size = 0; ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, sd3, size, &size); ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted); ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); ok(present, "No SACL in the security descriptor\n"); ok(sacl != NULL, "NULL SACL in the security descriptor\n");
if (sacl) { ret = pGetAce(sacl, 0, (void **)&ace); ok(ret, "GetAce failed with error %u\n", GetLastError()); ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, "Unexpected ACE type %#x\n", ace->Header.AceType); ok(EqualSid(&ace->SidStart, &medium_level) || EqualSid(&ace->SidStart, &high_level), "Low integrity level should not have been inherited\n"); }
HeapFree(GetProcessHeap(), 0, sd3); CloseHandle(token4);
ret = DuplicateTokenEx(token, 0, NULL, 0, TokenPrimary, &token4); ok(ret, "DuplicateTokenEx failed with error %u\n", GetLastError());
memset(buffer_integrity, 0, sizeof(buffer_integrity)); ret = GetTokenInformation(token4, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size); ok(ret, "GetTokenInformation failed with error %u\n", GetLastError()); tml = (TOKEN_MANDATORY_LABEL*) buffer_integrity; ok(EqualSid(tml->Label.Sid, &medium_level) || EqualSid(tml->Label.Sid, &high_level), "Expected medium or high integrity level\n");
size = 0; ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, sd3, size, &size); ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
sacl = NULL; ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted); ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); ok(present, "No SACL in the security descriptor\n"); ok(sacl != NULL, "NULL SACL in the security descriptor\n");
if (sacl) { ret = pGetAce(sacl, 0, (void **)&ace); ok(ret, "GetAce failed with error %u\n", GetLastError()); ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, "Unexpected ACE type %#x\n", ace->Header.AceType); ok(EqualSid(&ace->SidStart, &medium_level) || EqualSid(&ace->SidStart, &high_level), "Low integrity level should not have been inherited\n"); }
HeapFree(GetProcessHeap(), 0, sd3); CloseHandle(token4); } else win_skip("SYSTEM_MANDATORY_LABEL not supported\n");
/* Start child process with our modified token */ memset(&startup, 0, sizeof(startup)); startup.cb = sizeof(startup); startup.dwFlags = STARTF_USESHOWWINDOW; startup.wShowWindow = SW_SHOWNORMAL;
sprintf(buffer, "%s tests/security.c test_token_sd", myARGV[0]); ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info); ok(ret, "CreateProcess failed with error %u\n", GetLastError()); winetest_wait_child_process(info.hProcess); CloseHandle(info.hProcess); CloseHandle(info.hThread);
LocalFree(acl_child); HeapFree(GetProcessHeap(), 0, sd2); LocalFree(psid);
CloseHandle(token3); CloseHandle(token2); CloseHandle(token);}
static void test_child_token_sd(void){ static SID low_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, {SECURITY_MANDATORY_LOW_RID}}; SYSTEM_MANDATORY_LABEL_ACE *ace_label; BOOL ret, present, defaulted; ACCESS_ALLOWED_ACE *acc_ace; SECURITY_DESCRIPTOR *sd; DWORD size, i; HANDLE token; PSID psid; ACL *acl;
ret = pConvertStringSidToSidA("S-1-5-6", &psid); ok(ret, "ConvertStringSidToSidA failed with error %u\n", GetLastError());
ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token); ok(ret, "OpenProcessToken failed with error %u\n", GetLastError());
ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
sd = HeapAlloc(GetProcessHeap(), 0, size); ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, sd, size, &size); ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
acl = NULL; present = FALSE; defaulted = TRUE; ret = GetSecurityDescriptorDacl(sd, &present, &acl, &defaulted); ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError()); ok(present, "DACL not present\n"); ok(acl && acl != (void *)0xdeadbeef, "Got invalid DACL\n"); ok(!defaulted, "DACL defaulted\n");
ok(acl->AceCount, "Expected at least one ACE\n"); for (i = 0; i < acl->AceCount; i++) { ok(pGetAce(acl, i, (void **)&acc_ace), "GetAce failed with error %u\n", GetLastError()); ok(acc_ace->Header.AceType != ACCESS_ALLOWED_ACE_TYPE || !EqualSid(&acc_ace->SidStart, psid), "ACE inherited from the parent\n"); }
LocalFree(psid); HeapFree(GetProcessHeap(), 0, sd);
if (!pAddMandatoryAce) { win_skip("SYSTEM_MANDATORY_LABEL not supported\n"); return; }
ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
sd = HeapAlloc(GetProcessHeap(), 0, size); ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd, size, &size); ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
acl = NULL; present = FALSE; defaulted = TRUE; ret = GetSecurityDescriptorSacl(sd, &present, &acl, &defaulted); ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); ok(present, "SACL not present\n"); ok(acl && acl != (void *)0xdeadbeef, "Got invalid SACL\n"); ok(!defaulted, "SACL defaulted\n"); ok(acl->AceCount == 1, "Expected exactly one ACE\n"); ret = pGetAce(acl, 0, (void **)&ace_label); ok(ret, "GetAce failed with error %u\n", GetLastError()); ok(ace_label->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, "Unexpected ACE type %#x\n", ace_label->Header.AceType); ok(!EqualSid(&ace_label->SidStart, &low_level), "Low integrity level should not have been inherited\n");
HeapFree(GetProcessHeap(), 0, sd);}
static void test_child_token_sd_restricted(void){ static SID high_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, {SECURITY_MANDATORY_HIGH_RID}}; SYSTEM_MANDATORY_LABEL_ACE *ace_label; BOOL ret, present, defaulted; TOKEN_MANDATORY_LABEL *tml; BYTE buffer_integrity[64]; SECURITY_DESCRIPTOR *sd; HANDLE token; DWORD size; ACL *acl;
if (!pAddMandatoryAce) { win_skip("SYSTEM_MANDATORY_LABEL not supported\n"); return; }
ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token); ok(ret, "OpenProcessToken failed with error %u\n", GetLastError());
ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
sd = HeapAlloc(GetProcessHeap(), 0, size); ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd, size, &size); ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
acl = NULL; present = FALSE; defaulted = TRUE; ret = GetSecurityDescriptorSacl(sd, &present, &acl, &defaulted); ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); ok(present, "SACL not present\n"); ok(acl && acl != (void *)0xdeadbeef, "Got invalid SACL\n"); ok(!defaulted, "SACL defaulted\n"); ok(acl->AceCount == 1, "Expected exactly one ACE\n"); ret = pGetAce(acl, 0, (void **)&ace_label); ok(ret, "GetAce failed with error %u\n", GetLastError()); ok(ace_label->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, "Unexpected ACE type %#x\n", ace_label->Header.AceType); ok(EqualSid(&ace_label->SidStart, &high_level), "Expected high integrity level\n");
memset(buffer_integrity, 0, sizeof(buffer_integrity)); ret = GetTokenInformation(token, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size); ok(ret, "GetTokenInformation failed with error %u\n", GetLastError()); tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity; ok(EqualSid(tml->Label.Sid, &high_level), "Expected high integrity level\n");
HeapFree(GetProcessHeap(), 0, sd);}
static void test_child_token_sd_medium(void){ static SID medium_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, {SECURITY_MANDATORY_MEDIUM_RID}}; SYSTEM_MANDATORY_LABEL_ACE *ace_label; BOOL ret, present, defaulted; TOKEN_MANDATORY_LABEL *tml; BYTE buffer_integrity[64]; SECURITY_DESCRIPTOR *sd; HANDLE token; DWORD size; ACL *acl;
if (!pAddMandatoryAce) { win_skip("SYSTEM_MANDATORY_LABEL not supported\n"); return; }
ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token); ok(ret, "OpenProcessToken failed with error %u\n", GetLastError());
ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
sd = HeapAlloc(GetProcessHeap(), 0, size); ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd, size, &size); ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
acl = NULL; present = FALSE; defaulted = TRUE; ret = GetSecurityDescriptorSacl(sd, &present, &acl, &defaulted); ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); ok(present, "SACL not present\n"); ok(acl && acl != (void *)0xdeadbeef, "Got invalid SACL\n"); ok(!defaulted, "SACL defaulted\n"); ok(acl->AceCount == 1, "Expected exactly one ACE\n"); ret = pGetAce(acl, 0, (void **)&ace_label); ok(ret, "GetAce failed with error %u\n", GetLastError()); ok(ace_label->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, "Unexpected ACE type %#x\n", ace_label->Header.AceType); ok(EqualSid(&ace_label->SidStart, &medium_level), "Expected medium integrity level\n");
memset(buffer_integrity, 0, sizeof(buffer_integrity)); ret = GetTokenInformation(token, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size); ok(ret, "GetTokenInformation failed with error %u\n", GetLastError()); tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity; ok(EqualSid(tml->Label.Sid, &medium_level), "Expected medium integrity level\n");
HeapFree(GetProcessHeap(), 0, sd);}
static void test_GetExplicitEntriesFromAclW(void){ static const WCHAR wszCurrentUser[] = { 'C','U','R','R','E','N','T','_','U','S','E','R','\0'}; SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY }; SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY }; PSID everyone_sid = NULL, users_sid = NULL; EXPLICIT_ACCESSW access; EXPLICIT_ACCESSW *access2; PACL new_acl, old_acl = NULL; ULONG count; DWORD res;
if (!pGetExplicitEntriesFromAclW) { win_skip("GetExplicitEntriesFromAclW is not available\n"); return; }
if (!pSetEntriesInAclW) { win_skip("SetEntriesInAclW is not available\n"); return; }
old_acl = HeapAlloc(GetProcessHeap(), 0, 256); res = InitializeAcl(old_acl, 256, ACL_REVISION); if(!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) { win_skip("ACLs not implemented - skipping tests\n"); HeapFree(GetProcessHeap(), 0, old_acl); return; } ok(res, "InitializeAcl failed with error %d\n", GetLastError());
res = AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &everyone_sid); ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
res = AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &users_sid); ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
res = AddAccessAllowedAce(old_acl, ACL_REVISION, KEY_READ, users_sid); ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
access2 = NULL; res = pGetExplicitEntriesFromAclW(old_acl, &count, &access2); ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError()); ok(count == 1, "Expected count == 1, got %d\n", count); ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode); ok(access2[0].grfAccessPermissions == KEY_READ, "Expected KEY_READ, got %d\n", access2[0].grfAccessPermissions); ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm); ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %x\n", access2[0].grfInheritance); ok(EqualSid(access2[0].Trustee.ptstrName, users_sid), "Expected equal SIDs\n"); LocalFree(access2);
access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; access.Trustee.pMultipleTrustee = NULL;
access.grfAccessPermissions = KEY_WRITE; access.grfAccessMode = GRANT_ACCESS; access.grfInheritance = NO_INHERITANCE; access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; access.Trustee.TrusteeForm = TRUSTEE_IS_SID; access.Trustee.ptstrName = everyone_sid; res = pSetEntriesInAclW(1, &access, old_acl, &new_acl); ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res); ok(new_acl != NULL, "returned acl was NULL\n");
access2 = NULL; res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2); ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError()); ok(count == 2, "Expected count == 2, got %d\n", count); ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode); ok(access2[0].grfAccessPermissions == KEY_WRITE, "Expected KEY_WRITE, got %d\n", access2[0].grfAccessPermissions); ok(access2[0].Trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "Expected TRUSTEE_IS_UNKNOWN trustee type, got %d\n", access2[0].Trustee.TrusteeType); ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm); ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %x\n", access2[0].grfInheritance); ok(EqualSid(access2[0].Trustee.ptstrName, everyone_sid), "Expected equal SIDs\n"); LocalFree(access2); LocalFree(new_acl);
access.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; res = pSetEntriesInAclW(1, &access, old_acl, &new_acl); ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res); ok(new_acl != NULL, "returned acl was NULL\n");
access2 = NULL; res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2); ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError()); ok(count == 2, "Expected count == 2, got %d\n", count); ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode); ok(access2[0].grfAccessPermissions == KEY_WRITE, "Expected KEY_WRITE, got %d\n", access2[0].grfAccessPermissions); ok(access2[0].Trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "Expected TRUSTEE_IS_UNKNOWN trustee type, got %d\n", access2[0].Trustee.TrusteeType); ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm); ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %x\n", access2[0].grfInheritance); ok(EqualSid(access2[0].Trustee.ptstrName, everyone_sid), "Expected equal SIDs\n"); LocalFree(access2); LocalFree(new_acl);
access.Trustee.TrusteeForm = TRUSTEE_IS_NAME; access.Trustee.ptstrName = (LPWSTR)wszCurrentUser; res = pSetEntriesInAclW(1, &access, old_acl, &new_acl); ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res); ok(new_acl != NULL, "returned acl was NULL\n");
access2 = NULL; res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2); ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError()); ok(count == 2, "Expected count == 2, got %d\n", count); ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode); ok(access2[0].grfAccessPermissions == KEY_WRITE, "Expected KEY_WRITE, got %d\n", access2[0].grfAccessPermissions); ok(access2[0].Trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "Expected TRUSTEE_IS_UNKNOWN trustee type, got %d\n", access2[0].Trustee.TrusteeType); ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm); ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %x\n", access2[0].grfInheritance); LocalFree(access2); LocalFree(new_acl);
access.grfAccessMode = REVOKE_ACCESS; access.Trustee.TrusteeForm = TRUSTEE_IS_SID; access.Trustee.ptstrName = users_sid; res = pSetEntriesInAclW(1, &access, old_acl, &new_acl); ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res); ok(new_acl != NULL, "returned acl was NULL\n");
access2 = (void *)0xdeadbeef; res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2); ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError()); ok(count == 0, "Expected count == 0, got %d\n", count); ok(access2 == NULL, "access2 was not NULL\n"); LocalFree(new_acl);
FreeSid(users_sid); FreeSid(everyone_sid); HeapFree(GetProcessHeap(), 0, old_acl);}
static void test_BuildSecurityDescriptorW(void){ SECURITY_DESCRIPTOR old_sd, *new_sd, *rel_sd; ULONG new_sd_size; DWORD buf_size; char buf[1024]; BOOL success; DWORD ret;
InitializeSecurityDescriptor(&old_sd, SECURITY_DESCRIPTOR_REVISION);
buf_size = sizeof(buf); rel_sd = (SECURITY_DESCRIPTOR *)buf; success = MakeSelfRelativeSD(&old_sd, rel_sd, &buf_size); ok(success, "MakeSelfRelativeSD failed with %u\n", GetLastError());
new_sd = NULL; new_sd_size = 0; ret = BuildSecurityDescriptorW(NULL, NULL, 0, NULL, 0, NULL, NULL, &new_sd_size, (void **)&new_sd); ok(ret == ERROR_SUCCESS, "BuildSecurityDescriptor failed with %u\n", ret); ok(new_sd != NULL, "expected new_sd != NULL\n"); ok(new_sd_size == sizeof(old_sd), "expected new_sd_size == sizeof(old_sd), got %u\n", new_sd_size); LocalFree(new_sd);
new_sd = (void *)0xdeadbeef; ret = BuildSecurityDescriptorW(NULL, NULL, 0, NULL, 0, NULL, &old_sd, &new_sd_size, (void **)&new_sd); ok(ret == ERROR_INVALID_SECURITY_DESCR, "expected ERROR_INVALID_SECURITY_DESCR, got %u\n", ret); ok(new_sd == (void *)0xdeadbeef, "expected new_sd == 0xdeadbeef, got %p\n", new_sd);
new_sd = NULL; new_sd_size = 0; ret = BuildSecurityDescriptorW(NULL, NULL, 0, NULL, 0, NULL, rel_sd, &new_sd_size, (void **)&new_sd); ok(ret == ERROR_SUCCESS, "BuildSecurityDescriptor failed with %u\n", ret); ok(new_sd != NULL, "expected new_sd != NULL\n"); ok(new_sd_size == sizeof(old_sd), "expected new_sd_size == sizeof(old_sd), got %u\n", new_sd_size); LocalFree(new_sd);}
START_TEST(security){ init(); if (!hmod) return;
if (myARGC >= 3) { if (!strcmp(myARGV[2], "test_token_sd")) test_child_token_sd(); else if (!strcmp(myARGV[2], "test_token_sd_restricted")) test_child_token_sd_restricted(); else if (!strcmp(myARGV[2], "test_token_sd_medium")) test_child_token_sd_medium(); else test_process_security_child(); return; } test_kernel_objects_security(); test_sid(); test_trustee(); test_luid(); test_CreateWellKnownSid(); test_FileSecurity(); test_AccessCheck(); test_token_attr(); test_GetTokenInformation(); test_LookupAccountSid(); test_LookupAccountName(); test_security_descriptor(); test_process_security(); test_impersonation_level(); test_SetEntriesInAclW(); test_SetEntriesInAclA(); test_CreateDirectoryA(); test_GetNamedSecurityInfoA(); test_ConvertStringSecurityDescriptor(); test_ConvertSecurityDescriptorToString(); test_PrivateObjectSecurity(); test_acls(); test_GetWindowsAccountDomainSid(); test_GetSecurityInfo(); test_GetSidSubAuthority(); test_CheckTokenMembership(); test_EqualSid(); test_GetUserNameA(); test_GetUserNameW(); test_CreateRestrictedToken(); test_TokenIntegrityLevel(); test_default_dacl_owner_sid(); test_AdjustTokenPrivileges(); test_AddAce(); test_AddMandatoryAce(); test_system_security_access(); test_GetSidIdentifierAuthority(); test_pseudo_tokens(); test_maximum_allowed(); test_token_label(); test_GetExplicitEntriesFromAclW(); test_BuildSecurityDescriptorW();
/* Must be the last test, modifies process token */ test_token_security_descriptor();}