diff --git a/doc/install_ontop.md b/doc/install_ontop.md index e44633c..cbf9090 100644 --- a/doc/install_ontop.md +++ b/doc/install_ontop.md @@ -1,6 +1,12 @@ # Installation on existing client -An easy method to test the lmn-client is to run the playbook manual on a fresh installed client. +A straightforward way to test the lmn-client is to manually run the playbook on a freshly installed client. + +This can be done in the following ways: + + On the client using ansible-pull + On the client by checking out the lmn-client repository and running the playbook locally + On a target device by checking out the lmn-client repository locally and executing the playbook against the target device ## Direct call via ansible-pull @@ -9,10 +15,10 @@ With two simple commands you can install the lmn-client with default configurati Steps: * Install debian on client (via USB or PXE) -* Install additional packages: ansible +* Install additional packages: ansible `sudo apt install ansible` -* Run Playbook - `ansible-pull -i inventory.yml -l localhost, --url=https://codeberg.org/DigitalSouveraeneSchule/lmn-client.git -C main lmn-client.yml` +* Run Playbook + `sudo ansible-pull --verbose -i inventory-sample.yml -l localhost --url=https://codeberg.org/DigitalSouveraeneSchule/lmn-client.git -C main lmn-client.yml` ## Checkout git and run ansible locally @@ -24,10 +30,12 @@ Steps: * Install debian on client (via USB or PXE) * Install additional packages: ansible, git `sudo apt install ansible git` -* Checkout Repository +* Checkout Repository `git clone https://codeberg.org/DigitalSouveraeneSchule/lmn-client.git` +* Change into repository directory + `cd lmn-client` * Create inventory - `cp inventory.yml inventory-myschool.yml` + `cp inventory-sample.yml inventory-myschool.yml` * Edit inventory-myschool.yml e.g.: `nano inventory-myschool.yml` * Run Playbook diff --git a/doc/install_pxe.md b/doc/install_pxe.md index bfe7a8d..de90ab6 100644 --- a/doc/install_pxe.md +++ b/doc/install_pxe.md @@ -2,15 +2,28 @@ * **Using DigitalSouveraeneSchule repository and LinuxMuster.Net tftp** Simplest solution. Playbook and default inventory from DigitalSouveraeneSchule codeberg repository. - Linux kernel and initial Ramdisk from debian repository. + Linux kernel and initial Ramdisk from debian repository. + Client must have access to the internet (noproxy group). * **Using your own repository and LinuxMuster.Net tftp** Here you can use your own inventory and make many custom settings. - Linux kernel and initial Ramdisk from debian repository. + Linux kernel and initial Ramdisk from debian repository. + Client must have access to the internet (noproxy group). * **Using your own repository and livebox tftp** - Additional kernel and Ramdisk from your own infrastrukture. + Additional kernel and Ramdisk from your own infrastrukture. + Client does not need direct internet access. ## Using codeberg repository and LinuxMuster.Net tftp +### Requirements / firewall settings + +The computer on which the linuxclient is to be installed must have access to the Internet (add host to noproxy group) + +The following resources are downloaded from the internet: + +* The repository is provided by codeberg.org +* the Linux kernel, the initial ramdisk and the installation files are loaded from debian.org. +* mscorefonts from Microsoft + ### Modification LinuxMuster.Net server Create grub config for device group `lmnclient` on your schools server: @@ -25,9 +38,12 @@ set default=1 menuentry 'Installer Debian bookworm (amd64) + preseed + ansible inventory' { echo -n "Enter domain join password: " read adpw + set vaultpw="dummy" + # echo -n "Enter vault password" + # read vaultpw linux (http,ftp.debian.org)/debian/dists/stable/main/installer-amd64/current/images/netboot/debian-installer/amd64/linux auto=true priority=high \ - url=https://codeberg.org/DigitalSouveraeneSchule/lmn-client/raw/branch/fvs/misc/preseed.cfg interface=auto \ - playbook=lmn-client.yml adpw="${adpw}" --- + url=https://codeberg.org/DigitalSouveraeneSchule/lmn-client/raw/branch/main/misc/preseed.cfg interface=auto \ + playbook=lmn-client.yml adpw="${adpw}" vaultpw="${vaultpw}" --- initrd (http,ftp.debian.org)/debian/dists/stable/main/installer-amd64/current/images/netboot/debian-installer/amd64/initrd.gz } ``` @@ -47,4 +63,52 @@ classroom;mypc01;lmnclient;F2:81:6B:C9:E3:EF;10.0.5.51;;;;classroom-studentcompu * confirm `hostname` and `domain` (you will be asked in network setup) * ... Get a cup of coffee ... wait until reboot ... login (Logging in may take a few minutes after installation) -## Using your own livebox server + +## Using your own repository and LinuxMuster.Net tftp + +If you fork the lmn-client repository, you can customize the preseeding and inventory to your needs. +Use the instructions in the previous section and customize the repository in `/srv/linbo/boot/grub/lmnclient.cfg`. + +It makes sense to encrypt your inventory via `ansible-vault`. +When using encrypted inventories you have to provide the vault password by commenting in the two lines in the `/srv/linbo/boot/grub/lmnclient.cfg`. + +## Using your own repository and livebox tftp + +The next improvement will be to use your own livebox with following functionalities: + +* Providing linux kernel and initial ramdisk for installer +* Can be used as cache for debian packages (aptcacher) +* Can provide mscorefonts and libdvdcss (multimedia codecs) +* Can be used to boot live systems (netboot) via pxe + +### Installing the livebox server + +* Install debian VM and configure network +* Install additional packages: ansible + `sudo apt install ansible` +* Run livebox playbook + `ansible-pull -i localhost, --url=https://salsa.debian.org/andi/debian-lan-ansible.git -C master livebox.yml` +* Set DNS entry for your new livebox server + +### Modification LinuxMuster.Net server + +The file `/srv/linbo/boot/grub/lmnclient.cfg` might look like this: + +``` +# ### NOT managed by linuxmuster.net ### + +# edit to your needs +set default=1 + +menuentry 'Installer Debian bookworm (amd64) + preseed + ansible inventory' { + echo -n "Enter domain join password: " + read adpw + set vaultpw="dummy" + # echo -n "Enter vault password" + # read vaultpw + linux (http,livebox.example.com)/d-i/n-pkg/images/12/amd64/text/debian-installer/amd64/linux auto=true priority=high \ + url=https://codeberg.org/MySchool/lmn-client/raw/branch/main/misc/preseed-myschool.cfg interface=auto \ + playbook=lmn-client.yml adpw="${adpw}" vaultpw="${vaultpw}" --- + initrd (http,livebox.example.com)/d-i/n-pkg/images/12/amd64/text/debian-installer/amd64/initrd.gz +} +``` diff --git a/inventory-sample.yml b/inventory-sample.yml index 5cca733..e12857e 100644 --- a/inventory-sample.yml +++ b/inventory-sample.yml @@ -2,10 +2,9 @@ all: vars: domain: "{{ ansible_domain }}" - security_defaultuser_login_disable: false - kde_desktop_pkg: - - akonadi-backend-sqlite + # Comment out on productive systems when ssh key is provided + security_defaultuser_login_disable: false ## Proxy configuration (see: doc/localproxy.md) # localproxy: true @@ -59,7 +58,6 @@ all: # - vim # - mc # - tmux - # - debconf-utils ## WLAN configuration (see: doc/vpn.md): ## @@ -105,6 +103,7 @@ all: hosts: localhost: + ansible_connection: local laptops: children: diff --git a/inventory.yml b/inventory.yml index 81076e7..dd5bcb1 100644 --- a/inventory.yml +++ b/inventory.yml @@ -1,649 +1,705 @@ $ANSIBLE_VAULT;1.1;AES256 -62386339393366643763383339373037363365316132633835363530353330653839303732353335 -6231343438366132343632383066386163336532373633330a626636643034633261373662313138 -37336632633465646638363763306436333566376133656237373731613539363530656266336339 -3339313039373766360a306631373166663330373233343762613631636432306333383265313639 -65656638306665313862316137383939393336303633646463316536646162323563383263623637 -39323134626333333661666636326636313263396663653864643262373733326535653764313065 -31656135313263313535386364623237376336616430303737306534333839326531383964636264 -36336164656636366431346434643536663361313634386233356132633133666237633037623439 -37356136383063356530336230373231623062306163646235633633623439346634636161623062 -30383438663361373938653630653562366436303235663963363631656630303165386465396632 -30313639633364633439346230666264363762646264396336663934346533353562636437316461 -39636665346565343437303032313761633536633266653866643235316464346533666536316664 -39346662373338356639613238626237353737363533396330653239373033393665663263353165 -36626265323266333337363365356538393933616266613965353662323263353832386264363337 -35656631656365366132303465306432366235363931386238633265656162396632656463316465 -66363734663233663866656263353631323762343665353535356561313237313036393138636163 -36386562333339373832383364373465323862616661343865646662626331646639646164313439 -30333239346136303432323035626135623937353862646562373336636134633034393837656164 -31373932323135353836646236316163343966643731343831333033386338393737303264626134 -63373862383732663462656639643335613232633839386434633832636534376133376432643638 -31353136313538376531613239373965303730323536393039633861393338323861306662313639 -36366636396364386136663865613564633566666262656538373637383133376333623934666262 -35373134633133383535353436613932333466383961313361333730303164353463633531356561 -34626335653335306435333364636235623862616266353961313138663032326338343665343035 -66393562373835656634326164643638623364333239613363333138303938616337623366346663 -37343662663239396666633038386636633963613934616461363664333631663663316531626266 -65636661306635333839393835363839383763343164616631666238373737666366323232346234 -32626630626564353433393463626566383331343365396336646239303462633665643439633538 -36383365356435626237663630353364396166653365653363663362663838376532666236316663 -31393565363962316632663463313063333331316564383031363939646361363837623037626630 -32393761353066316663316165666434313766653666653537326638353165346438663565323836 -62383434616266366336363537376166663261303834353531323835626463326132326432336338 -39316464373362646333663763663334363035393336366266356639393735373563616130343931 -36383862363162613161343836313737363663353763323831306561313931343835316565326661 -34383236626335316266646362333535626338303962363632373663653136383138336263393435 -34326638353762343132393537343166643630666433386538326634613862313831633361303732 -39363862306562313765303066663932636531343935383466363738373039306135646162613164 -39386464623439356635366666323433303235303866653962363932643964383432323064636334 -63356231623139663661353364666432323335613738346130343536343633396333373963636234 -33623734323966626532663030646362323765663661383364613734663066313363653566303965 -64313136336236346430663636656634653039626165613631636532323164323330333263646366 -65393337353136396533393961613738336366313138373432306263393362613735336137393763 -37623365616139613638623664333039346533646638353538346464633465663634373463653963 -31366632306437616435356339633561346237373833356565663139363534373037626566356339 -62363739653934636635386465353163346263353034343861656135336435393930663561396634 -38393335303633326330373066623135336530633032653537366631343961346639656539666231 -62326134333364313237373035363637636265343236383931303438356463366361363936633964 -36393865626137353064613336656637353039353061353532663230396462363431393636663239 -61346565663764363666393034633239613431626133656134393661393435333334633736623730 -37656334656131623038363761343863643966313730316330363061326336353839623833643635 -35653333663239363436326131663537613735616632616165316435666134613862643265383638 -64323637623364313564313730643766376138663436356530663236313133353161643336663163 -34353735386433363362393336366236303132376235303163363231396266306462643261643730 -64333938353166333664383865616262383935666531633466653832383237623566353738376137 -63393937656235336432343163313933303532646432663437383635386164303039386535393334 -32356462626633623036616531383636633533346537316132623438663365373966343831333061 -33613431383038623162656262333031386265613561646530653737363339383631303137306131 -65643961393138373137613637396465346432333266303838653935373061316532636466316439 -62343863626564656232316236373735303734623933353634643337653036353639643139383462 -36616134373065616162336235353564663735393332636166306133373336373139643466653262 -62373735303130376534343930303532316332313737656434666665346133383534343066623634 -39383332626337323061373530666137333133653237353131363261366664623363393864616436 -32356238343137336430386262633962626466623438323437376566663666623236333432316532 -37356138343132393362373266396631353138373639363062623135666631383966313761303635 -33366136303632303965353634626334653533633737313032383036303430656662636230336137 -65653163326631636437363436663163376465373566366665333635326437376438633665336335 -62623666363435396561346436383433633936383261383639326535623861626539653833633738 -35626462383733363162616239343261346239303964376163636433313663353831633838396561 -30333331363336663336333937306437643332643332333061366638313837383532373036653461 -38316233346532633266373438336563613835316634396664663738366138613039616338353666 -62396166643461623136656266663637343862633237643665386530656436393363313134383639 -62386139663035663363653763366139396632656639623065383466633939363433393339323664 -66316138383238313562396462633731323037366461616434333865643363653339656364633265 -33613234613766626461366430343663633864363536646664323230323338383130306633613165 -33336133363466323062363961316632643133303962646230316336623731616230353932316562 -66303565346534363030323763336562353061633230373230303465336562396463376464643637 -63333137666562363135303264316332323031326638343032313934626663373362613133646334 -61653130636266633034383538636236313033373334613336356533633936643933336365346133 -37626263623035646232663433333532623031623462386336383032653735333335633931363733 -37386435343331393133333937626431303330613261396237306262623563633632323936316535 -65353638396430373937393536333565363830303333373863313762343465613861383262393366 -30633261326638383538623662653839393130323539646165646439613039396135656161656532 -65313662613533336161306639663131666132313037393338303261636433646434633761376538 -62626135633733323063316230636534393334336634643330323037393566303838336137313165 -37636632656338383664323264636132653432346164323533323739623730343937633938353735 -62313035323830303964363665313235313066336330336231613833316138326234393331636166 -37383731613537333464303431663236393933656462623165356335623165616661373665326235 -30333162636437346465633031633734623366356466396262613139623262326631666638326635 -32373631633234323365386532396561613366643139613539323266653130333537643465396563 -35346638326265343564343733303535643230663238336535343937626463343537653666663030 -33663563653865376135666633396164373332326336313130336661633136613233356237666137 -65306431636535356531333566303065643065653963313763393066353630363135336365656333 -63636239336264613161656135303633636336646531323534623063333439626331613138363239 -64656262313936616161326564663632653037663430653635356533393134663331353130366235 -38366639623662663230343039353861626432663933633137313238633332353739396436373633 -37353236363164306130326662346230336135663861346532383139663362656365646430373038 -61353932363561656537633534393430363236383566343839646231343730633864613036643530 -36633534343164376466336161333833653136376664353661346436353233616430396230386437 -64393430623864646334623137343537656563313865323336643064643766633035653265316539 -62636434653931613337336337383066373235653335656161656438373165616561323765323931 -31353661373532626231656361623038626361366632663764333764663737363137333732613234 -62376437393637316663353739333935343866373164333364346165313632313639636139356535 -38343639646362636635346634363064386636623635663536366461373431343362653839383138 -34323737313832343963366536666234363439386337353838323233376464646362343737313665 -36643237316238616265313332303162383033323363396330303766313734353563353133316530 -62643032326237626433363932666164336161346532646634363564326432396637346665636637 -36623561633861396439623835376434653738623862613333643162343362613865323363363434 -32633638306438653638343239383137396530356564356338623330303661663630656639666461 -62313232343461633636336538326537323266666466646261633336393464306438653136613637 -34336133623361336563306462373963613336383265646637313139653765656433346238386231 -31646362353736646431303937633033386435316336323062346235323232383466313566636162 -61366430313335313161333163393164353530303938386435623830353962373831393235616531 -31656565633534666164303532633235306133616536646161393365616231383866326635376630 -38666363386232633865366533373630356139393030626230653834613230346664383734616336 -39653736633237303161306632333138646633356463373063663064396561613162663138366339 -33326235313165343866363234353336643934656363383464353036353138626638373362393263 -36326438303366623137383530393434353933326163356634333837653830363037316565626466 -36643339376262386430383530343934646361303831633863653765303530373765336531326535 -36646330366635366339303731376662623366636163353738646535363363326437623439336466 -39373861323738363734613032383136313335306462386436633962666139366165343263616338 -64306536393966613235376264383463313763383161343634336362393865373865383366313839 -65623761626166366437323234373130393237643963376235316535646166326663646335353036 -62366562386364343734313261363636636639633639663830666130613833383766316461613236 -37653030326661623838643861353339353562366537346535363065356235393963376331623064 -36316464626439353464393638373963326333373037333761663239343431626563313735363031 -33613663613038326465623462623565343963333064623464313039376332323935353736616262 -66646161623564316439666431393462633463633432643763636535326538356135663535383734 -30323063323361376165626436633632636234653062623337346562386338663733396532323331 -61316539393566306334616435343665623931323866313636663033663161383964646430663263 -38663833303063356637343130323362313734646564633261653934666665376661653033373934 -64393934616465383964353464336136636436323563366562623839623862366332343339613334 -63373063656663316138653939323165383735623263646438376533316638623734636261663035 -33636465396431356334383063633866623063316163343262623831616137643165366564646532 -65303033313137636562353238663564303034393166313864353330656335663233643763626239 -35346334386130653462343531336431623639376165653263373539316163383038336636613136 -30626137666133623063376333646134643536653138333464623930323931613461366465633437 -32386531323739343363373737326263323836333438356133613065306633326131343838333363 -62356331623163393230373838383866323063633739313339353839336232363430323165666531 -34316231376232396464356436326165616266323430313632393362313966376563613534633339 -61346532386537356262633936366533376239616531373133353633336235316534363436393238 -34373232383665373539346664316463613962383961386530323539313538306165383038333736 -31343463373938636630336364653931343931363461663261373333363336353438613266333232 -66316333613134363630366632623861363135373335613837653937666466623163613231376431 -61623964353534316464373737326134666538393662323663306563633430616363353833373131 -61323563653235646139623139303162616235323664613463336364326638363762653665666433 -30656634393965306436616261303330313037373030353266383833326539626263326462363833 -36656538663733313533653864646232333934333031363433613839323632333166313162646461 -32653935393738646163343263633563333132616436613930613038313462633735636131653265 -64663439323665313130653931623564373737616632386338336465363564373233616466393934 -62373763326533343830366438386430306166323834646362313838313662386637613961643138 -38383362633730353730333335316439663631396430623135313565313431646465336631613666 -64316638646531356563666631626663383939396461313631366462326161643730346436633734 -63626633303336626137333565306664616363386162316264636331386134633461636162333835 -66326139393733373262343537323136633233616331373730653966353736613538633430643264 -33623731366330323161643230393635646366623139326534353561616632636338333232386431 -35353539333831613064626165386536636664373933633833363736613335323434383663336561 -34616130656232326631613835646131353936326631396334663335386236653066326564656238 -33623065303039666461383864323031313737316565366133326136333138393731653731663036 -32663135323464653030626430303439353030393865316266383164616233613039613032353130 -37326430373439363631323061333431386430613361656439303734393730326264643731326638 -37343836393439316330653432303633303439623337613336626662323338633535346563343938 -31333963303866313763666436653265306164633731376432663634623131613166623535656362 -64643232383863633261613061373131313933626666643631666238663931336566343561333439 -66653939353665363065656631323130326664343464303338333161623639383962356538623237 -33656337323733353738353034636138656138373762343336316336346264393434306338336136 -66643966336130346263643232373334626433326334633363616337343466313438343133366637 -35336561353531306164316639643262316235383631626636633133343837663032343032613362 -33356330343833333438663465363364653633306134646537656361383864356461393963313666 -33316236326665346233653331663132313531663263623762393039663365303333663231373262 -63643634363762393863303739626162636131366564623333373534316461383861646332373532 -61343736396465646538363765653864626636376361333935366536343133666432323530376333 -36333664326538336438323138393561616536343932363733316164316133656631333233626562 -33376234663863623365373365303936376164373530653839393631303732356662663536633135 -36326439646465613363633233633836643162333164663266393161626231393138616538643738 -35303532636532656266623434333162323230646636366334663238613733326237636232623763 -37643066613361313436346531373835343131613061326366643638396633626261303630623338 -32313632653336316531333065343830656365306430623565393935333065663537316130633936 -66376231626239383165626536626564306331623935336331666662376264643765396464323135 -38353438613435333864326633326530623036396665313762613865383365366137303166306436 -35646238306262613432333434346639393939333264656530303637393566633934633062666661 -62646537306132663164643663313138646639363131346133616366313137333965396137316433 -31613439613433383663663666313237613336326134343437373637363038643332376532383339 -34663735386235313532633431313630366537326135366132373063333035613939363832336433 -65663230626536666565303031663062356639376538396531346263346139386436633434623363 -65323462393138313932623239373132326463323830616237323665656437336562333666396366 -30313632363138666534383631313366653532336238303036623235303866643632663335653066 -32616363326134343038336431393436326565343732646438333336386366383066346231353833 -61363565303737346561643938666133363565383632346465656335363864386236393432633832 -34663863393063656562623134316235366536663638653563323465666566613464373666376530 -37366364633537666231653065366664646632393638663535643931633264616431626366626563 -66656561376664303838653437306433666131323761323639663665376262386564336363376638 -32343661326138653734316161356130313636616434623434613765386538366131353036643532 -30353237323831373562376332346466366437643165633738623066636563393036623765376639 -38303135306563356533663238386233646636306266353034343433383830383330653032663130 -32313932303338646637363762653232613138373665396436336264353534623633616138383235 -30373433626332653032343937653964373161343462393139336235396439303739346330656166 -31643936333139656232353932326531633566363366306466666137623832313435333161366331 -63333432383034396439323466663235656536663831643035626332373234643837666630626332 -64363531306531393737666230363631336666366536363464353266303633663563316234653634 -62313135346639376366306463383837636531353564306530623134373236613635303132383263 -32326663376138393633383132643964656365633966656231376439316165353630623764326137 -61303234646566343863653130343738373331373433353732663837326334633530666636326434 -31336135613431326131353864613331643137396661333566303632336661626134666565623133 -63383865646464613537383533636462333133386639363837653436366237666164613639396666 -30643034306330393062313132663661636163383336373134663130666132373534383734643731 -30303163353563306465383134626137376630373731323939653531356436323337616662653565 -61313131663262636437666531623466623438326136653332666238336566623963343334623266 -39663134636666326261633634383264393662383733353663343734306534363934356165663638 -62623437633031663364306231663162616630393531346130333764656431616161626466343462 -64333865396463666161363134393932613636333330316136363737336130343663653063623036 -36393038336462373933313934353939336132313135623534393361656639333864613637626137 -66656331376235636661363534393163336439656264396663373665383737633263373934643231 -61316436343539646662316639343662336438383335383838373261643838396439316632653838 -64643135343938366236626463613036386230316263376165336232303434656230366561646164 -62656466396439666363613634366633623935376630313034633230643162333334313436643930 -34333837353937636339363364353333326238343536623131333561376230646237366437333836 -37613363663663656266326439316334383837613633336339396335396539636562636334316338 -61313536316364386262666663396261356538306536333761633763303762363232313332373438 -65316263353165653336343562343164306566353630326333653664356165376361326366333964 -64623261393636626439343738653731663130643839306639663239623834366364613832326233 -31396432343136306365393132613531303632656363303833313139363939356132393230633966 -39383432613135646435396262646461623735313135356230383533613136656639643539366233 -34306231313032303537626532316263663337303362663635323731333561343933663265373639 -39313461353561316539643436343764636665316233303438643736303464363839313135633333 -38653936663234663830313632623566336333633561656631336132323231353432323031663863 -66613363343431656437633631336638383932653336303762613730623534633936306333646135 -61613261613932653361623263656237643534326132613339653861343666393466613439303734 -31303430343132636332343134303936366262333566316638636233656330333734636636376164 -36383536313534306535336438633435353463353630326461336366666535313638363862616136 -36616236353033343566626332646133656235623162633736303762306430336238663835653263 -61326466663161646531383137333439656531383566303164366637656661306638623439323164 -61663163353263373864323734373434303530643764633762303139333336323832643063653734 -32373266373239366633636637613433336532663135626238333936353431343532316536653061 -37393131633066666637623538633530653730323362373432656439333332366638336361666239 -63646631633762333938636338323537343734396133313332393436326630383639333034643961 -65643139303531376163613833666532333734633438623935353635613635336262373432636462 -34323738386631616266313462346265356164316238323239646462643762333166666132633965 -37333535376235613538363938353135616366393964346164633861396331633139613463393035 -31313262356436646261636139383431643637383235623334353861343064666437356465373339 -31323364646635306163646131646339383931613461613330636561313235663934376632373132 -31633235346339373763303138356464646231373266366431633038646533616161613462333231 -65623835353963376532313535306331636639643635323434323362326462376239383630663962 -32393634366233616133323531633030336635623134393730626630636465653065633462666661 -63363637326139333030633333626531353866633839376661646437353939316166366137363865 -35383536666462343135623266363939623335613632613830316432343363313538623364666634 -37646531346433336365653935326437343461323861336133306233613931636231316232643034 -35396539373663633237623862623964383463613936623061376333323439653963633861663631 -64623866396263663038373561656239643664383233336433623036393930636264303662643434 -62366632323864633733626135343339623030636334356331393732363139326662326563663366 -36313262323933313631633562343230363032656636666465373062656664333964323537633362 -30343266393230393665626463316639336665383763343332333339383464333533653135353365 -34306135613839326361623663633033623238306234666564626565313137326431383763646433 -35316339366234353936326466363435323331353165653531373733643232356236383838303930 -61373538363238613635313031653434396265316434353335386332666135323366393062376162 -30353730613433383364636164306336396430633133333839383261366162363930303131303762 -32373461396264643232623337643266616562393865393864363161616337636436383131643932 -61316232313835363634353930636664323539643133333632626631666430363534383866656631 -30656634333836623133623731373861366333643637336566353064393332626461376334333733 -30383164306561383738333238353766666565656137643661623466313535623936353831303863 -64653762656364356664383365343264306336663563373763316532303537336138613238323438 -64376130656466393564613766633036623336393931313132393430313663373334353134363030 -39646665306137613034653830666437333832393464343265336162393231386437303539363861 -62333032393134666331363030336463363639366235656266363830653337333965303934626530 -31616532323334383665663936376130396334656137623537646663346166343262353764653439 -30396332346235653462633034653535396361383934646632386534643530313134343034323636 -32383538636537316532626230363361313330653534353962363932326331323966303833386330 -34623632356136616166636434633437356261313233333165303237346464396436343931376263 -39633963313062623636663533316538356162613734373830363838346133383564353336613437 -31643233343437393765376431613338383331363632613632396265656638646434663631303363 -35386332343033623534666530363831343262343736333366396238643030333337313838396534 -64633937636332313432326266643735383262643334613034643465366666336638393461616361 -31383038656235653239373164666265663865666537663335396137353939343233616435646362 -36393266633863393965363163376332383837626532343034363034346665343663326163653266 -61666236653837316639333832636536353534626365333939343734633863613032666437383864 -64326234303438363434626566306435376237336137316465626432383234383434343666333332 -33363333633132393265313662313731353162656337363730366439653532643438333639393664 -32623561636531376234613565323661613635623337303963653862393435663562333137383531 -37353532666639326334366133376162646262666439616135316432333934656631326566393965 -61643135653965343032316339353433323636353734313834666163633431366331393035393564 -32313966346634646263623130653934323736303364653930633439343339343432346538303831 -62333462343533386166623831383437373732373037356236376530353639346662663930336235 -65303564313939373532303137376565356364353332663961323366323264353738306331353963 -38343333653764323835303432643230663733643132333866303039656136326630303962643963 -39343737353166653862333030356533316165343766646231306532336530343964633136326563 -38646330386438373931323961653832613638303261653333396337623331323837623431656137 -33373631336462623531326438323739653662613139393866383263343134633335383738656363 -30333665663063373661623761356438633262356334373262613934333064326239376633633039 -66613534326662343435383438306133613765326361376537663331323938623436636164366135 -35323730363036643765376537336432333066303137333534353537633234626666336334333530 -39396133626434383132373435343165383563383564323864333639623764633064353131633165 -33333862613538363233633735653730326633346563383732353563643862356561616261393731 -66373662353937646462363262363865343531366463393761316665383230313331626630326236 -32353439323039316335343237623730393966356132656534633933333737653935613932643231 -63366163373062656630316661623131333462366564333462336333663833666363396639373936 -64613530383861643339353965666530663437356431353731623464336461383030306563393262 -39346566306565623331336234646439316461646366636566386236323464303138306663373265 -39346135663264366566623731656532323236316130383865346136353238353534303736363635 -34623532363033656437656235643066316364333164626662333536396631653531323437643564 -66386635653436616461633162316165343638326264303066633437313734383666623636666538 -66636634306532393339346633356431303537636364323832633737353139313138346632356238 -39393634666138383339323335306462623330333931326266366135616666613533633531653539 -39646535383666646662653936386231616230306536396432333536313834646538643936303366 -63666431663965343336343362356465306461313532616462383233316261336439663936313639 -35663261656534613634316235663139323937616261333530393235653836336138353630636335 -65616236366233626336356566326633646664356264313736306665316434613535393535353038 -38356331343436626230376334303138303962316231636631656233396231336437346435376532 -35316232306137333332663236393631636436633736353962663332626233363536633733353436 -62613565616332353461633930333636616164656635663064623463656238383430386135353030 -63626534393930663462323634343936346261653635636430616564643630313836316135646638 -36613363613238626364393434383966376430373838323461653131323563346364656330396562 -66373231643732316138383236636535366339623865393935383364373765636335656139396261 -35326339343266663863636361386431623238633139396264613166343564353236626237616161 -36626233356361666530323632393437623238663835616539373939636434353966643734653835 -30356437353566323266353233646532383335363366636333336335363634303038633965376165 -38306164663837366633306633393163356564643533663134653439663666316366383666623536 -39653666303363346131383064633835323261343361396462343566613237313732323366373864 -61313762353737616633633538616162353761353131636336623265313861616634376434363961 -36366662313737653465353363313537376361613534383563303764356136393563306230613466 -33356437613965633661336164633239346666636137666332303430633766643036346439326134 -30376636306436376564623338636231366536663530353537356461663864323234663530626633 -63656535633336346631386163643138326638663061373331623762376335646661316362363636 -36333732336138663034386139326566616236373061636661373038306135613031633139666635 -36626333646631636437323334653164316335396532396536356261346438383265643535306362 -62303034303161386465393062623963303131363165343066633765656431303035646664306661 -66333531383665646166393130386463323537386237383632333431333265616664323364306564 -64656463313133386330393266633932643863656436396265653161323665373861393031393338 -33373463303032326231313035646564663961363031613362356635623030376465383337373033 -30336263326364613633656532613439333631343665353866616263323137613163363333666664 -61383831616630373836343233373935633262383136663931643539653337643232363132376364 -65353662343539373437633133376638653633393864343866633865306231353264306262313261 -33366332316531616234333766323232343336613564313135656531306535643430636666346234 -38343532653666636235373366356635343339346237386436633234643738633033383664366264 -31396464366363323937333834626230383038653434346361316166343930366536373761353433 -62313638376132373661316436333430653735393737383235386164636535386130313533633830 -63616335643233373165393733613266646138353437356666316139633933346565633561353734 -30656261636265306633396633383638646233623164383236343335626432613866653834616434 -37663861373062653061316631373064336663353061306261303733313632373163326261663262 -32396263613639383534386236623836303635613631393763313130656134656236623238353661 -38643538343135386131393133336237373733613238663763653431636436376232646637386339 -37626131396237396239323031613265306262326466656634363266393064326631383633656338 -31313130343064326135616433343533653563666663393230363735633239363537376463663466 -61353865333361373538616236393235613366333635633664333631653361333962386462373761 -30313066356564363432363739346430346633386436613739363939336665636239323930636130 -61633639363635353333356266383661313638353162373535613165333063343332383231633331 -63313339306235303361393362333635313331623365666166383937313663376261653838376563 -37386237393762356339663434626639363666663931613832653539616630343137383230346163 -39326138383165326131616639623033633164626466663439386333393231373537616439326161 -33366634313739346266663564343330653062393139616464393634313234336165356338303439 -34366537613163653339373062646431643537316635343438343031613937343734356130636230 -35353334323130303439613233333439303234313530343861316261613036326266396134393938 -30393032393864656661346464666262343431386364626662353736343234363861663437326532 -65663835306366313362656135386430666633383165623965663838646433613835363836643365 -62373730343831633033613631396535333232333331636163366162613131356132643835663766 -63643531663237333935393330353733323730643732386362333734316632636265653731663039 -37623365336562623766643833653533343238396139336231326262326330316338343738663031 -37383334333634366464653836353238373061386334333437626537616135363736313364306366 -34396636383934306664363835633965353463333465333966306537353735323564643565623261 -31343932316537346561316662306139343266636463393130653434666666393338366531303734 -66323965346632306535623931326133663161663464643337373761343661633763393666636162 -66346566383937626161633339663732666436343437386233396332633261303533666436396430 -64303566396530616365613935623763323962616564373130383637623334636134623637326465 -64303037333035303930616133396336616432663338396634383037323238623961353136323965 -31326266383838653236616435313936396537323761636436626539323336663037316161393433 -64626233323935396232636337316634623037656231653661303462333961346230666230313834 -66626661643231386135363565336437633738613263636364663336313137376635396162366235 -35316638353430393837386265356465363834666366636432656237646634666533636631663530 -36656434353038626332336263353832376563363035373437316262383733326661353762393934 -31333532656666343136343635343435386337363962363037336331623239373035633631346337 -31316231623761366235303538336339626134653238343132343838346363353266346239353663 -64613566313263626537333830646439396536366135346362333162366539363537616332386262 -32663862313739316330636334346664353666363933623563643365383630373866656537633033 -39373331663663623831383830656237653034333932376263356566613162326566346537373632 -36356161643766343934643636633633363135653537396333613532656464663535653863323066 -63393662666463626635663062386430336233613637363263306564353563616439666436656162 -62363330376430336663393565613736306165336630383336363263643032653062346661343766 -65646537343063663864333933363938613438326163353235306239346236656561346264343039 -32616331373062323066306232383030373130303565666463326434383331343361393331343039 -65653536306538353830333434373433333030353465313866393966666434663238323232323364 -30343535383631313431636462356630323439323965353033383536363866323461373538666332 -63623935343665323033326432356432323730353864646431633035363831313735623063316465 -34623064303864393365373635353263343033653064313163633936366564616661346532343138 -66383130396232353166613531343338636664363164613165613737353762333466616530643937 -65666530363165346331356262363065653861386261623566346135383030656163303332323436 -63306137623430613661333733643161386138623934313863643561313061363061663435353335 -32353362663064613364653236613862383830356431333839636163623432346638303230666438 -38353766646231383436636463346436393561613339316430323463363731303762353330346532 -38646130663862323466326136313332306561613933646637366235646338343161666161383431 -37626230303633303664366161653437643331386435363631313935643764643835383662353536 -65626132313961343564373538396237363934343335633231656362316238633030623365663063 -30623232663930643639303437336563363131333531333238333663333136353964363439363836 -37376233646330323364363764393732326462316235393633626134356138653430346537393764 -32393739363637376534313836346239626639636332326666386334636234353535623035363266 -64633661383438363336656539373033313635626239313232373233613764323665663762343461 -32343938653135313863316233376632396666366636643036623566393739393537333235396239 -34303034396138656531343662613838316363646461643136643432653132306466623837303532 -65316139316432633039373239326539383165313430656364646336333863303464643961346363 -36623830363235316436306563313239636463613537623962393061616632356632356136646531 -66653561323232343231613863356466643030303066396665623638383662666465373833343733 -31356563623761636630626630356362646164373662383562613264663966326631353237366130 -34393439356263383732643665323431653738633236313539366535396664616261333232306535 -63306662346465303835616666333434393361306462653861323430366566353435333231353935 -34383264663930303662663462626535346130613033396435653934633933366464343166306165 -64623461323365623634346463386234386561306339613461613438663034333334643365343531 -32303637616336616463383566386139323639613731303263646162613262343531306665326261 -66393038653234376132646136613263383531656632373631326361313332613739386465343935 -37626331633063336232326333343037646432323265326131653665333863653337663961383737 -36663361663232373338623931393538393461646538646565323730393562353836623263343832 -38303333386363313634643930663832656262616537666531393536656664303539306563653265 -64666538333135656132643637346666353930356635393764333538396662316366353166376433 -33626232383666343030363263626266656538616562663735353534663164376434346631383762 -31376561376430333036393131356564663737633064616361353038633839656164633536613631 -66646665613132623062383465623738363330633039373135343333363039643332363331333365 -36306636373238396430336530633763613332336432363933303733346133653666373132393063 -30633437356363666235326263386566643062343534353238633062393565633838623839316634 -62323239376532383163376237366431313734366665646161626232616566323631383536656632 -36653535643537616230626633306630383934373135363538656339626432666563663638316363 -30316262336461303438643964366434366332336535343437666432663566323761306563623261 -30633965623530346165633936616366623536666230363130386633633061343730373365303833 -66646334646634366433626331626137386531323661386132316235613966663730336432333764 -66306532303566333834613537666639616663633466633633613832363164623536373738613265 -38323038343862323166663533613830666362353630323035336235393565663230623562356166 -64306331363234336433323364316232653934366662323465393961393862373738343063316434 -36343035396536363136323734623132373763366636633939616339323965306564303031663331 -63306463623732373462313035623532646334623532363666633461613066323933393433376463 -62626563666565663438393332646435333939653439306234363930303637373965643366656131 -31383834666565623861356531663164646165313638353237643831343337313362306232393737 -36653062323561346661326133326635643363336465616636316666613335623235346161376136 -36666264633232653638626138643934616366663938336562353333393265373137383833356234 -32303638646436393865656336653664313136653831336636386664333965383461663166356363 -30383139323134303035626438626632613562663164393934663636636338336134626530356134 -33643930643532376532303466396264386166646166316166366661383263666563333764643365 -38633438306538316338623631616337303933373432646664313736613035626365356433323737 -31323364616464633830643133383661366161613137356431663330633032386136326334343264 -61633333356230326236353330316264383738303033323930666562393932343235313932666133 -32623636643563623166383231396433303735303534356334623330323933666636366365626266 -38653038306135326431343832336331623564633364663033653766623832383630643964643032 -35633431663062353339333266633835366430646563356434373537393937313932346432623633 -64373632343264353066633436626531636232653038613263653038323830616164303361393732 -34643233633731373637336137383763303736353237316134393835663032393861353934633038 -30626531356333346336373535313433623035333466343066346265326336643162323133656339 -37323561326137653939303839343837393763653465363462356161363963353865386539623333 -35383637356666633731396638643966303063313430393038393234346433646566326632363637 -65306466613230353261616366323634313837373030623563613562333833653263346230376439 -35643836346335373261326365336531353733636236373466353332383737613639633034323161 -66393432653336636362313962616237316232663038343665343065313030313937343834356436 -34326266343364616366343039303332353161373263313730373839643361326333616464306133 -64643863633336363762306131303431636366613038623562653035626537353466643231356561 -37393035656533666638336637373932346662346436313561313964316139613763616335316435 -33656230356365373365633830653835376639373365623663346635396361333338376139666232 -33626662616662626363636564306530613034663039653636663838326162616263343562393661 -64353134363737623139633734306430353265323835373833373261363031383163343938373862 -30363735633531376230376161643037663762316466396134626462346133626264353064333039 -66333531613735313333376336313565376632346565373134386433663935626363336635356337 -61633264363635303833613462346263636433383634326330393236663835626432326336396133 -36396462323365633338663935343733346365356233653436613962356366383365326262663236 -34316233626130336635333933646463663461653364313338343534633630663733336261363431 -37343664333633383536633464326466653432353733343933616264316364666661396631336135 -64306637623234643735643430323262626539383439373363356139643362663939336665376139 -35613864303837363635353564393532336162393566313339633866316266363261623266633032 -61343365393762386465356164646531313865633633313866313162393431393132613131643462 -38646131363036313964333930663234396139613362326331333538376364323461353839366562 -62313066663830313862326162326166356537653135313036326239353032636634656433316530 -63336532663935616633373261653666333662643561313235353466303632623364336165623334 -63346334303762326363643838336362616466333631376135643466306638313038353765353034 -61613033623132653930623634376537643230323330343534646365356339333938396565336533 -33303730666433646465623231306233353130626237353236373836333438666565626566326531 -30373637353237393934343064616663663762343135313865386331326266386639353430306130 -39353534663362323665616166373733623639333164656633363537613437616635363639316232 -37373365336531323639663935313836313338653030396133356365336437373963313231636332 -65663433646665383836643362383739653663636338346137636263386366386234306130303264 -30393266376138646465613436613736373662643365663330313230346139613465383136333463 -38626661643165356364626164663164366534316462376633653231626233393934303333313963 -39643362633761353731643239663334646266613536383661626462633062653231616236326332 -32393634643030656535633139336132343639313939313436393865336361633430376166313230 -63383435663766646537363136373138316166333031663736616461316134343461356438366361 -37326663343434323563613231633530316364643164646464386361656632633539353135303432 -34386162376235326631653764613866323432366166663966356534346463306231656665346333 -35356633356262303236386633316539363536653438633334623161343136623161313463626633 -61373637303630633233383430346534613336363739653332376461383531653832333264356163 -32346562636662323066643932326436326333323537323932343033653862356163353730353438 -31313531306462636131626136613135646231343633323065623363643661303336313463373130 -30636630623734636536366631653031326162383034623233623463326434366635383836613361 -61356463336335646662353735333662633231396331336336636235663839353163616234363733 -32373438393730656461383537353038653739326335313732636639656263643033346635316465 -63306437613863643932396361346335303331366535393863613663313133393730333039306233 -63376563366636313435623664323632383139653932643461383536313734343430613736393734 -38313061623163313931616564623366353266333237643639366166313564336437376664303938 -30306233633437376233353237393331313734633063666165323637363938353239653539613439 -36346232626466396431386664396535663162336166313438363265353232363365633034383331 -36393164386235613134663566666539323539313735383636303631336337386366643561346331 -65353962366336653139356433366465616637386333636439333365396563363663656231346333 -63366636336131656237396234353837303035323637343265303566333761353431613135356635 -31313664316635636564346531323638633266356634323164393563383935343738346632333237 -35656464356338356538366664636265306165653334316363336435666262636634326636383934 -36313136373038326363366263616438306561653565656435643063613537643732643332363037 -63633962333637326434363936346633313634363961613063303664323761313533646638666139 -64616436366638353166656133323131633461363663616336353730336639653463383033323061 -30646237653463313261643237343933663032346133336339393965626166623066373735623836 -30653331656635373838633062333638333037316439323663323838616530663530623434653964 -37616362373331633030396261333038373162336536373731396363646334333665396630376263 -37656634373138636633386163393234613434376265393065306333353661326266636633323634 -62633031363965346337363031663263313538393064363761366336356462383737313633353236 -35613261653563663663663832373664383262306232373430323934376330376166363738343962 -61323863336664383266313264613563636464363566356637396261353039626166623331626234 -39353762353536646338613066656533303332666664353863343838356464616437623934343263 -31313838326531356432353563326334643665663735366233666534343733323865636562326530 -63333166303936643736623066653832346339343133346632343164373630616538633936633631 -36376663343934666133343535646662623038666633616130323163346533393765653337353832 -36616563393930343065666361376635326464333435303736386661396263346331636131386336 -64326665643536363563343964623536306238376535656330323061663431653532633434386634 -33346133656630636565613065323634616333396363346534303163393337613830366662303731 -61633530393463633635346136656366333030623038616439363631383466303962333238373661 -35386332613264303739343931336366653431393134303833323464383439656661303163636464 -61363462363064393364633061336262353261336662363462636462336462636535366662333534 -63363666626137636633356631653862626639346634373238353636666236623964373231383264 -31666563353034386365636264346464326237663235353136346339393436383035663034313630 -37333963373135643430653761643662353334646439313262393635656662353439616334356338 -65313166643934623065353164633965303166653830306165333837346262393563616335343764 -39313033373339626534613838343239323661613530323666356665353431356439646231613638 -63323862353230373562393039656361376434366237653365373937336332313762333561386432 -61343435356633396465353133333066333563313330396234626165393364653031353939633731 -37623439336262373838393533626162333937623133396365373034613962623161393231303562 -65626133623833383465396632366137396135363434306337353038333633653264616437633635 -66396435663931653534643239613636333862613263613434396261323238333461623661613437 -64633331393461333831633162623333623663376165343530326262613362653730663463313039 -33316638623664663837383837306163663461373636643032303933366338303633613830356665 -34363165663232386237643464646163663136396232626138333165653162303339616362396230 -37383766313039643438346136623864326334653938393039633961373339376665633536336437 -39383033393635613034333634373834386266626534363833313534393134303138363162316533 -33653333373962643965336465326635653732306338656631356564363961366462636230373030 -63393837356631366638663964326530666536643932343861616665633331373230336530356138 -39303738386166336334633433353339613366643436313064653333626130313361656237623163 -35663263633136373765343330343338306636663534383730353235636434656138643466383261 -62373661616137613164363665353535633637613263646361313337336533363665626462383633 -61383731303132393138663639396433343530336266633939653366633438626139666161653638 -62623866393533346136343339363334666333613666613031613135626235633564353463366664 -30393130356664343434633132313537383063663130646464346263636133303034316266303739 -30656661303231303434333562656237633233616539333239303266373363613034626263613531 -35393937333761633232386333353134613362396138353030613934353935356637623630356533 -30626431366234383834383866353436326333386564353537663136623761623736313861366336 -31336331373537313739353933303261336238613630636462353031653133333139306363326566 -32373264306338353638393965343933656162373438373366333338623434313032373538623835 -63316434306262643532616232646430316635306535316635326564316664353063343331653963 -61306530396630323031386534653062636533613931613632306637343364623464386137623330 -39396166306333346665323139356135643662363564633631383362303636616336613732383763 -35353861343565383739336535623962666239663963626162373861343738663364386439353133 -62666232333533376563383536363239366135306134616439643738306331643539383034663363 -37366366643838666338396537373232623232326263616165616639353939323463663638643132 -61353038646233646231393961663863373466306461373832363435613635383836363633393039 -64346134633837333332366135363736323234336235626630653965353039663964383535373931 -63303262346661373535376161393136656436303235386333663033656164363636346632616433 -31353932643266343361626431383835623761653633656131373134633163343137363536336661 -34316633386263306432333338313462393031383832333533656436336230666363316133396162 -65663861616538306333373032626539663535373161383462366164373764343437323562626136 -38653336663263306533376466323132623261386166666435353438663763316665653039623532 -38323730626666353636663830373765383138303330386663663737623531346630363936393966 -37663839623464393136303934306438376362313233643838373939323938666635626630633035 -31333466393833393361393965353636616661353166323937313032663139386431333163663035 -62373265306132643465363765376663623430656264613839336234343766613833323235353333 -66656639366130656534316639306638366465336661643263666337323030666263623036306362 -64316634353139666434396261653161646339663263663131386339346631653932653834626562 -62386665616131386138633839353262353230316264383130656330313333326538636261393863 -37633665613631343130313163376337363963653134626131643531353565666537613636373663 -63333633313561363438653035303563303532613736373634613362313663386563656339656634 -64616666346532376537336130353233623832336237376663663837643134636361616533666530 -63373065663833363734356130613230613739633134643766373935396531373965383862656330 -32306639356365383332643462336331383731643864636264633234616132386538396533613432 -32646638656233333661626335306361646435306234653436323361643866633235313962313637 -61333637663463643066333562373535363439636666643538626133623432643932666662653233 -33306137613735626135373430393033373132356666633337303134323231323235326434323639 -63326362306136333065393734396339336665313035663637303533393834373664623864386234 -31313062316334333130336138326132636366356266653531333435386231653063646531353933 -37326533663431376461383632643266663531626235393131663464373439396666343236313262 -35316165313962383632623262366164386130323065646436343236623230636664306539613031 -37363564343438376637386366376139613332623765663166373731316262303630326234383063 -35303330333364303366363135376262323365633561336264626333323564396132346362626164 -30623637333263366164373465353562356561376238353332353461623939633035643562356266 -64666131376335663832373136646266633363386139363864363939386534636461313237666661 -31383063366362306466633039363730376130373661366331643836356533303062323030396330 -35623431663561653264383531626136653363336339366332363431323635393561363763613134 -37643733633138396432623031666333616136643735646235346632306461313136653837326135 -36643935303264303532396332356561643063373263303536626433623264393432343933363237 -65616237656131356537366337316437363831303064326436393761623734303238336334653131 -38363437373264373636653531346665666363616233643563336133316439643663336263613964 -66613835336638386631386565343233313435356434393637326339623933306134343332316132 -64326434393134643866323935663331336539396636303666623364363133613861303366313736 -61623465646336643161313839326333316632653365626231616264616633623336633463663232 -65313465313965316139316531623863373235633362633731636633393534663662623663623533 -65653762623938343833653639373730363932366330373237653830316438356666333636663938 -66353139333162376439306530653839306436393832333030336632643830376663653132633633 -36373965646666613436383931643662383263633066356666666362306430373636336438626231 -37653338336462616333353937626363663765346664623862616162353865633463393263626537 -32333336383633383237613731346465613635633633383065643038333536616331333966373232 -66663231343266393865663165383937633439373064383636323137363566646133616332656566 -35343335376465653939653933393161396265396136363936656433316566613336613537623365 -37393364326337633362303662656333613934663362323331343135666136376365663765346439 -35303465303163333732343737383135303635613865346331376537336566623561643837333433 -36633930376330623737633836376239663333616134356530623264303337666432326332646433 -31633034303166616134353736613838383231666363623563316430326461393462333564626335 -62646337643066313563343466303231643334666437383135393432663538623464313735663431 -63336166323839656531633862326534353136303264616266373431363036643335616562363438 -63643464356662333065666663643464623139353833353536323466663462313630366235303065 -34623433613736646465616466633232656362356137366634393735623031343531633231306334 -33393137343637343734613133366239306135383931353637313561376161666562396237386436 -61386637376563346633303032626361353462323963366233613566643434666532383965626661 -66663165336164313431653363653939653262326537623630643237636163613066323434653633 -38613939316463663833643062303933383165393939333233643139666462363037613032306135 -32643266333938653962366231363364616339656137646432666466653363636265643364656363 -32313966356238356266356339636465376133653861306233343635303135303735623037383339 -37626335333030643932306164316535353933346462666337353366633966346363366337623133 -65343766653261353365643039333164663231323031393233623062366432373430396563663264 -37313962363831316137663064313631646433353033336537636132623663393637336438366463 -36393565633936346134643465306639633737363431656161376533633434636663656535613037 -61643330383366663266626436326466646234333831386632633566663831336437646563333635 -65616339626561353065626462633530633461643764373866376264636337636431366638623839 -31366338653632333037353233623962303866303334353033343739636637616239626237343764 -39356464396239383235396132316665366238373833303266343535636164623862656139613064 -33393264363634636231653235613133656138663763326263386334303537333733653132346533 -61383739663963643365393638616233323138616131376461323233643262656633636435303566 -32656438303466306361653366656464303335663661656437373031356365336334373961386264 -32396230326431376137356534336566643137356361316232333939343362323766393232373639 -35363465356235323331333265303535623630666236376230633364643237653762386630323836 -38363136373331623964623964373163363930313138393030353636643930633335323761383764 -37316135393466323139643738366537396133636465393565613765633938306164633263653032 -35353931643438633436306464316230333437373532356261613565643164656330643862386635 -36616237653834653134646439636266643131613761373833346338623439383861636330383133 -34616630313465303535613032626536303762623331653435333633303262326464306330393832 -30623265346438656137383937306366646530613564306230353939626366653536653738323139 -63363332626532346462313635353366333235323837353961323862343334353232313464626236 -30633336316465666637626239373730383965653737663639336261306264343530643364663561 -64666265613762313032633837333433643537666562653534643364346637356363653732306561 -39623538623763653136353464663164356232623333363033646666396232666261323233653661 -65393536653237383863653134356134653533316631623231616539653861363538376362663066 -61646261656336363931303935353764313562653736633431633263656261623039613737373432 -31373165386161373038643831333937333366636230326133616430346131386663653964313866 -37626234396631646639626436326466666561303734346134653764353234376136656662366539 -39376161616162653337353235643236323832653835356235363634346365346462346162306333 -61326534393264666163383466616166626463626666616438653765346638383763636338376463 -35616466306230383233366266653064343962393731393434363435333466616462376633336338 -61643061613963666636336366663562346366616135326462383864326562346534353032343662 -37363861653866363630373565346266623037663233326432316562356661333538666332313465 -33333930343965313030363262653862626461393162653135666666336262663634653333313434 -37373030356665616238363438613739366337383961666662363364343535393033666336636465 -39333431353939366439393761343039626663386164653330663135313839356535393362376135 -66353531353461333539633135363832393235333535333066373461346363343863323239626335 -65313638623638313437303865653736626133653239643232306437663237313432346633616565 -37303539333830663235393862396665313164623263353932313036333362643361383732346631 -33336330656565616331 +30303837646531376332363331656363313831373537326436653761373133346530303466613261 +3534323830613936363363323763323635353063393362330a666637323739636330646637393063 +30613938363232363031303961626265636266313030303234623630633133333337323631323831 +3732623163653932360a346165326365623036396630666564643564666336303430303733383530 +61646231326539646635636162363461346565613335343337336430613135383434613936653932 +31613262356364663638386639363465303731373562353431353262326332363436366164633635 +66653562376233343861343337643364653934313537623436346664623361313838346230323136 +65313830313830386563306132376361633231636536646265386662346565626237383733376365 +37666637396536643935626430343236376331333161313138616138353961613637363934313134 +33346362323366373962353338386237356565383061613634313130313738393535393231303764 +37383936336266336262353763303739623230663536313034313739343664643737633863663361 +62393466393432653831303538633436313837613063663237366537663230326361633463323732 +36323738366638346464626461643731306661663735636237353762383434333537366238323762 +63656534303763313362643963636335303064666536306362353763363063653934653165346562 +38636430373039373239666563366164386364316462643865663634663233613037643662623062 +37616438346131316239393439323936306437366532633232666631666266363063633536316566 +61353364353030343434383161333666323534663662356466666531346639666463323230633632 +63616163616231663033623463323833313137323865343030633061643061323666363661343430 +39633161336130383964376332343964613363303436326630623861646435313463613532663464 +32386232323064373432386237663236393435373639333661373735623635313664653138383330 +37653838646439306236626462353239323465656466396164323663383664623865343561303464 +38656330393733366539636231393466363030633337343433636536333065353962353732623734 +38663365656262353533303033623831346362303633336565616264313865623434366130343533 +30366433623036353937633263343636333563306434653163303338303565343537353134303739 +32393865616662666465646561346362646662636361643832326262363439306239626234393863 +61623634366563653332386237393330393864393532313337656236306431643338353266626634 +63366563643235326533643736313161306139333236313361356433373162336533323733643239 +33313331353565626535643130633064323031353163353366636232643261346432646166663038 +31373331393664353533376263353565336231633565653434353365653439336230633130656265 +34636238663932666364343563613433313139333165346538306134653239623765633933333135 +34343866323931323638663434303138383164643830383839633966316233346265353030646563 +65336264653634303836343939376562383136303537383465633538373663653538626463393336 +38353732393062386236643830396334363631363538336537663334643839623334373432386262 +62616530356663306432363661653365623134316161656638366364363636323433346534303931 +32353063353664396565646533306235343239306539356637383937363938363137356466623630 +31623335306335343234333731353533623738653933656632643935316165366434313134326136 +66656132386664613662626366343166346135623935366163393162323937653231643966313063 +65303538636634656335306533373363376432653130613133383534363238643231613539306536 +31343062623432313734306637626461643533633065343566376438346630326433306662666230 +66383661383463396463373131613837663138373861376539343734346561656239666638613863 +63636332393832346561643463623335343333656437326339333939323639386334616265316634 +61383037623130366361336637643434396461616634323532626631333135366138626164323636 +39336136353630386565363763643534616661363361383139623361663063313935336136343231 +34313634386537643337303761323865396535323064373763663565373031396266666236383735 +34376565396465623235383365306165666264313337326333396336376532336135336334396361 +32633032643338396261643366383162386366626535663666376430396232336238613263393765 +63643661306536366332386139633330623836326632653133623066346131333739363864343931 +38653362353333623237376431623134666334383036346663646465666663346336383639626534 +66306665626139383734373665666130326361386366313132636233333066313730336432396338 +39666562626338373363316565316231353762623130393162373366653334623665633138663866 +65353966303338636633323062343461366139356665366639316530633931363831363163663764 +36393338303734306164656432646163393036303164663033633235666534386434346336636433 +66393861343237373430366432333931303563356137313132303137373334376365626537666538 +35316364376539346435303736663338616534646436313436316239336333303939663333376532 +61656539623135346235313332626239653632396630306232623962653265353561353234623534 +62663738323039663461383966333565646339623139653832376638333935643430653831336366 +31663637323936383465336134663336643265643861323934373063363836656334363232343338 +61316164363032663530353339393332616535346438313035626632356437633631653036393538 +39303362336465633963393030623231306237633766653264333639623233303137623735323936 +35383061383133663932353463626464653435303139626331376136396531396236646665306430 +36636636646137653832373737363731666463366337343166386239623131633461643334656334 +35366138313038363265353365333831613931613834633763363633633966623531363633376139 +61336331306639353835656137356330333539616262333031313861343662376434376563633330 +61343163326231333561336363363764303566313732376265366336396432313330313235656463 +33306538313863613835646237383166396265326537373737336239623437386464376165666637 +34386639666131646365306163366331303538373265653435383832303135633065636234326164 +32383761376439663936336164393931333238376463666162316236613664313132653066386635 +31663439616365356563616334313664646338613636653464653731386234353963363862646362 +64623632343438353662343035396533373562623233333839383630363261653366356134393536 +30663761613462386338393738343431323138356134633934623932323338316639306637383138 +66343361346137663138666232356265396630326135643161366333383162626333366331373066 +32376566393636383439646433393937616264353963666363616462313031343034343366393434 +31663931343335623035643264383961663437636366636161326632623362396663353836383630 +31373565373062363664663037346663613964653133353833316339343266633761326565386439 +61663033393832303638313334323063373736663631643861373765353438303233303235663363 +62636630353938326630373865636431393033333562663433656435303430333165363638383932 +39313233363838326265613734366532636432363538636138373065346230346164356164616238 +37326435633462346466646464336637333238356638646537353133326363643639623933373734 +33343965353131663761326634373962623963363161383035306639383432326163656132653535 +39353666646337393431383266303037326165656438613561396564363435666165626264653037 +32646635646466373963393332623163643137336237323166343166636461353564626662323835 +64663934633163316262386139323862613562336464346534323438666535633136356337633964 +39383538613330646436393334303932306133613231376161636661343335323462343365636438 +61393831393962633435656238613161666530363335313531313063623330323130623361623837 +32303138656139306362333366383838643033623763323364333161353730383266613930653662 +35323036303734333661616134376364663831643065353232373566623231396439396134643363 +36323866613135343861666263303263333565323363646266353333353263626138386634303437 +65336635346234656532386539353234633666653233393636306336633661646165353436366534 +39646133363434343361333537616164373235383566343865623430633363303430646464393536 +39353764326364383337633839633339613438343761356663643132613463636630363533643530 +64316663333931346638633561303033303533653537653533333763353365363538366466656563 +64363662386365323436643439613834376635303765326263393035323435643135356335393237 +39656161613665383063306433373635353265313936383031313037393131393631323265383630 +32643236666361656631636234363664303232333962386130646566336434393739623266636565 +31383961376434306663326230646662343139316333386137383363343966646562356166653936 +34346234653263353036336566373238666235316234393634323863373663316563336337363138 +37613966336366326632343037316365356166336631313039636463356231333433666339366530 +36356166353239356133336163386539303061643238386632316239393031336632316439386134 +62313764363062396463656466633663663831396535613734306562356563613133643435643836 +30646166623237373334396263646134373365333361363433636364643634623437316530353836 +63363636616430326565333364306462336135303039646235373233633336633738323839333335 +33623134666333303962623335336538316133663934346132313237393538613237333037663836 +36666161633033356535333238373664396235383231393237316538396137353066643936666338 +35346533383731623464626237663736376537346139353064616330363962616137343933663762 +66356435646137663330383037343830646664323439333535663534633035393961633063373662 +39333731383237313633353064643066313932333331343732626661383533346539353163613032 +30613133363766313734656264303364616334386365393635343062643530396164626633366631 +34386132613632626237323634346137633261323564623364313862623665396639366562646532 +61363231366533396336346664653666646365623464623335323437383163313234303236613166 +61333230313133633432383162363166303032333932306565333339376137636261316362633332 +34373936313938366533313836313938656232626262313132316663623265623661383165346561 +61333539393539373966316639613036306332643838366635656663613062343335666162303230 +31663238656230306463323637336433613138323439303138373832316633663939386638623664 +64376230356530623535373665343434653962383238633463343237616464363666396163343965 +61333435376535626432353830323562306332383663323635363565666334313338643737323361 +35356465383366643035346232373037303066663539356461396166633031666530386435323438 +62623438323839383366646266326266656337643362393830613738636366653466393562306237 +36636561646263383264336338313137626266636635313632346465666135323264613537633036 +64633130646235306264626666386233333932643466356133383237626337373632313964366137 +36313535306565323638386134623261323532613365326363303530303862333761343930336133 +35313534653533653263333237373132393963346331303935666566373038653238353339643134 +66306661336235396632653866353561386264343835303163303733346633616337663561613339 +30633737306364666334336366656362346666343439663335353839313939646536343465393365 +39353535316264646433353930626237343963643931326163643838343637343666303663643065 +30303161643732633065343833653262336230633533656263656661393235346666336538663765 +38396133303937643133323439366637343138303932663230373634303231326630356166356637 +34336566636261343834323836396135636334663734653066383632376261373262376161666333 +64646135313462303466376463306463653736333730656264333939363364663736643130326430 +35626135363762313065613034666538383462653032343337303965633036663636343038323935 +35616264366663323830646139666236393438366130393737383639623463633661326162656134 +38353731336466303935323233376363326437653236653866643237383764616135666132656362 +36343339616238393965633264636437326230356530633962313532366264653931373166656461 +61326634376230393161346438633632653037656436376565613538343863333533383935303863 +33636263636166323233666130393931343861626333363261373937363766653964313337376634 +65373362366532393066313732303264383030386539346431383937373032656638643339306630 +64343764303661633437656539366337306462373531316338393236306264326565336432316266 +38366635356463333938303934333236333137363361386337333738336234356335396531333961 +38343537653464643331373964633932626137653030373766363036663866643337323563316535 +36336139316661356131343135353838353064346337633738303834616363356331303136653565 +31613765613732386538626134616365303263343863646362303864353836383664396238353037 +35326239383563323938313566396465323963383461643035646637396630353530646239363966 +37393632663236616438356439623837386233323230613766636463363837373161623161373233 +63623135356538383331303438356132366435333164353537346133313363343530323335616336 +39646238376630333237313939666138376334343331653266616532323366343833393737383038 +31316235666165666430323436303161316266363731366231373935623062303337363437636432 +63393562356539393461613733646534326162366538636332356633313433393862663931366462 +64633231306365323036313630393765636636383439613634393165636239663933323164616431 +64616163386539366438346635633731386265613332653036626535306433613531333431346638 +38313031303937356131323562656230366334613433316235653835326166333364663338393738 +62633639656534396262363133646439306664623638383138636465656266313030313965346534 +34396461656363663834313231326130393634303033666535663861646161316162663863393865 +61623331623734623863666432313964356139643062383334663932323864373735393932366161 +31376266633334373138663633373561623136626362663165356266663265636630323362313531 +66643966666434326435613634356163356235643535653539646632386432326664646439336561 +36306134363534326237376439333733663036613332323564303539386366303836336165633965 +37376330386632643762623634636130613737336261636161616363653931623865356138303366 +61326332653865376666356638653563323761366133356136366430316430393565396136306237 +32343866313635646238666232383736633066626438393134326430343738333531626435626461 +32396235633632373938346661666633653138303033363432363437616166613839623264613738 +65313662623734326236363362383431336330643830663136613565343361383230656265343939 +61396163386163366130356365363439636334396338353839343231386562363262646638626230 +65373066396332383232373265363964343439616530393335346462383137323533633834343166 +35353832326632633366376435333936323838623634653466356534356137376165333334616261 +64386133363634306161633637346333326638633865356564626533613738346133633435336433 +64663530636363353634636564363963383163353736343136653566356237356139356563666265 +31376664633834376264626438313734303238316363363364386666653966663035343533666431 +63323661303064656463336539393039363037616437363437356363356336353239663961346439 +66653633666662386132633338376431336537343039636130633766326561393332393162663863 +31653064653834323132336264313962633161333962343732373834353666316436383365313931 +32646464656436373165333132656330623633633935656261656664376162313565366465633932 +30656465663836653661643131323232353637663839376239306136303136313763303666366234 +61346337366463386437326237656634303736363738633634356336366430363564616166303463 +66333138643165383131373034333336353134333532656366373464383264363034373065346438 +64343161353562613535396437306532643731313332666636303436353830383037396133636366 +62353131613137643962366639646164666165323334396562393562383036316663626630326165 +63633431623566376166333461626134636631663661323531636137643936653737373539346434 +65313539323363336430633061333964376366333031316630386463336537663630626439343834 +63646533336564386665633434306663383039323531653466666565303232393664383339376465 +38373430373166306134396235386436326663363339366335346539626161636635623064356234 +62316639626162663361663835373564306233396366383633666431666534373135623933613437 +37613739653638363731313332386461636139373061646432393335353462376163316534663138 +36666338623066343165613631303038616164333065656165653931393538616366633861333233 +30616336623436633734383966663362633036623664336237333037633338623839316261353839 +35303464353138316631613636363835636637346364616636333638383530313038616163373134 +36313732653237626265613531643436323066373762643435613539366134313961626563363232 +61393433626561376534393530333236313033626338636536393435626231376632633634313864 +34393935356361326534343235343934316235323739633831393564306331666330326337343237 +37396661393965663965663433633339326561313638343366373138316161386163386165613337 +37623564636163366333383235653937346537613131666632303639656233346536363731316363 +66386565373330613730363635373735303161316661653236346136323932323166643364366165 +35306365633466636437323730326232303335356366386165666530353662623034336534383065 +34616463653566303434633466396366663665656663663662616363396264646536613533623232 +34333534633866343837386135333965373962393732623235343066396637656134663664623333 +35303964623565323432666335303638666561363632643732313437613831373833653230373463 +31306235643033336332323231623061346366656262643462383430396364393264393132626363 +37333461303366623335376333356639323739623538363863663533653032656330336535383464 +34356134613836373264616236393362643664633339633931613162383265306139663136326534 +34386364373264336162626262663730363662306437363239623239346532383334396534663166 +38663730663561613233306130633936313931646332613931303764323637366232343032353262 +65663439356438303666616262383066346534363633373039353232303566653166376666633866 +32373134316534616539353765336434373236633837333538356636373234623935353332353861 +36326639326561306364373934626562666438363865623235356534356561303730383835303132 +37623030663765623662633638303930366638323632383661373162643331373035303764323333 +66613431313334363835623263316631623731613435326537356333616463376536383933333564 +61313735646361306138663764633937346635666539346162323838633731306437383063313266 +32303365333639323166353335356438303638653934343934303735316236393934616361333961 +31613966313265666339366332383234383062656434393365363832636261386361633030363533 +35613266633632353738636265646639326234306664386132666363393165356431303831396439 +65313536373161303930363063326338353361343963366162643530373862393535613466303430 +37303466386661303164663961376566366266373937626564356663303163316639336466383633 +65393764323833386564396133616134356533363839333938633030356634353366366639613235 +62386134356430326139373931623364663961643661323930666466383439326665383030316234 +63653938333531306534366131396130303737353839623833383965366564353433333365366364 +38623235353934336164643836343039386565363334396166306430623461623734313738633161 +61313438383233303532626136663561363732323662656562313431316462313430346334623564 +35326265623430633135626634653333653037306631646432323562653538653934663063623437 +37666361343535623835663663343931363236323030376363663465656466373666636265336338 +33393439346633626264653537313065393761656362643233316533626166303461343437613937 +65633639656233353333633937363261336538323234643165393432616338623064653035323463 +61343234663064343632663133363837636130393939623063363332343538353733383036373830 +64346230326539336663323761663361643233663536333333396562373862306561316463356566 +63373437386661613438393032316130313364363736363331343434666534313437623863323434 +63623536303438396539313762646235303736333137383762616635373837383132393738313038 +39666233626233393334363866626338653564353531636165656462643966373032653765313635 +36646363616436343138316632626439623563326536313139333935636538646233626565313934 +61643631653766363530633966383238663939643964343065666666306335386432393264313136 +34386437626366393164373865396463333632376534646538383635633366656363326538373263 +63663937313136373630326139646137633962653431343336626464366432656433336532636330 +38646531323565386332363662653037323463636133303364363562306136616338633661386534 +35636534303562643939303236616263386665663131326138303830376362366134396366343764 +63636262613638613930343839386433383162303435376362623436336135363430376164393738 +37633861663662343463346535353332643461613765626562323164393034396330323639653039 +39393330613636366664326637636565616266363962653263613038623238343335346264353935 +34656535643938336230626233636133383132353931346661613464353163393461373632633939 +32663264326233656239323932343139353164626534343835363161626131386264656238326539 +38396266313336303139646164353332663636643564323565326566306361636366386531343263 +63643661376339333963653733373730613530653563383163343963656432316232386365633933 +64333137623761613839326433636138643333373939333335373863623336623935616231396537 +61316431643230313563633964336633326362356639313865626533383738643535613363663930 +31306464383338366165363831646130333064663166623566633936383865343132623534353231 +34616461633636613964613664333131386330646365376631623231303535336163643839306230 +65326635346637376238353134653232626230636661613537343462656431336461376338316330 +30316164646134636265383630383362353438326432653837643763616166353631303135393366 +39303238363663393134373461306630386161346566633730363361623433656334316663336333 +34336630376363346232633034646235383638656365323630313138373435316364366463623963 +36656663316537393236333864323938356232353839343033396162353338653163326535356339 +39346333396535653762343230323031313331376138383230303164363361333134373665646534 +63643031393665663861313334383061363539656664386262393232653665396335366439333539 +66343832626238666131646130383266653861623065623035373865393035386230336531613761 +61363063346461326537316536313832643733373931366231313161306537373133383234656439 +64343937616336653838386131373362373164616166636336653431653837303236333833346330 +64323737396231373533316336656432353236313061643436383731393933333339306537363432 +63616131336663346264663031653065626661313234373866663939313436373234306639313136 +39623036363031313866393961316565633665616532653732393664626365643263333266383564 +64626231366533616639383963313330313661353835353739373266653866643236353139626336 +61313431663335643830613139666464383033373630373035363966356130326665393662333336 +64393161663730663430393161373038333561373961623832653134333364323831653765613339 +66306663633333333238646335666635643133336666363262363532326666383936396565336261 +30343336623265643561333763663739653764623933646236306236623739356663343439623939 +38343363613537396630666663353535316639666663313537623237373063333635616133393136 +39366437323236613233653533383031376532323538333538343361623763333064396262616538 +39633033363663656636316635643962666238343034393764653261333265363538623431623763 +62363465343634653331633536356130633830306237666334383631303036356535633865353135 +37623839653135626461386633353337303864363966313066323566323735383565353563353334 +33333061626662356362393165393834393836626331343335663831623264383234656538656365 +37663163373462393239636533313634646466353239623265373833396630383764303634363235 +32646535333562643530643737663133343061316531313837393863656233306232323732343566 +38376539326663333139386263623638326634383866636335383461623931396630316331363533 +64623762656662306137323764633738346661383466363130623335386161363039643832343239 +33303836353862326266613065656564386663656162303730373563373061613030353833386130 +65663334643732366533643638616634363134393531633933333130363136653139626264313037 +39343531616335643463613132356430616630623235383563616635306330616531383533316563 +33333366653236316335653861373262616665663337346533653062346462353134383365393264 +30636362303262643762323762396336306230623431373461396631353639633633336539623231 +34616231656138303165323464323866623462366430613334306334633361356565626132313830 +33623165326330393836386331313066373836666364326434663766633361363133303539613938 +37323539663038613136313438366431316632373030323438376163633733613431326561313362 +64383936636536623563333961613430323431626432343165633031383334623964323538626266 +37656164326363663530376464663730303861363437653330313463626161623561376533393865 +63656434666133336266356437316538316363303337633238383631626139306235636138333265 +39396538633862663863316233623334386635353834366330636437663331666335396664303632 +61636162333662666235643565343739636364353063343565623665613963323435396132366266 +39373738363136666262663232326533666538383363636662306433613362313834383930656233 +61383936326663363138313135306430383466653337666236313036363361383738653935613432 +37396233393037313265313038646534623966393362663261626461323038353633333361363466 +34346139613366313634393164353333626562336437336565366633336130356639633162386663 +38653835666565383463353035376432663666613635346366613637333639636432633964626638 +34363033376639363138363134356164656232633164613333633661613065386566303530616139 +38363036626537383665613433373764346361663039316366653235663764353062653161376564 +30646161653863326336656262346265626463313731346436333964313463306365653832386532 +65333639336333306535383139326138316462666565333931383933653238303134623162653736 +32636130643136613039663733383030313162343266646639373730373161613361323163353534 +39333736306434333039623036333838393564393436326238323534613734383437353762363034 +33383933613334346432666231656565633762663030346132343036663264373436386462373733 +38383266643537306131396538323633666132336364623663353961633862303631346365393832 +33643036303831346135643334386236643565326665333166656137336430616665633537333030 +64323835313962383730653431323132323363633734303963313762313037346466346535363830 +65643233646265333963323364666632376530363265666532623232613261643138666337333433 +61353361353238616336353031366236643162363266393462353362316635306238383532613638 +64376564323836616464313839653337343561303138383464646231636131373636346430383634 +61613332323531316236623337363666326139353734633839393865616431653661323465393230 +37386661393564373632376436363066323634373837636233323165653032636266316166643766 +61633031363439343139616336653936396266376338343735663334666236653738623964393230 +65616138613434356562303463663338393262653762353532373832663961323865343239393261 +38336337663162323163613234653839333435383430323835383436303839633866363635316436 +34316534376132326537646131623262613132643030323861303533356335336132396266623739 +38623530616431383965356366653430323735333633303535633631623639613666353366636661 +39366439643637343139636331373636633062393562333030636630383838343230616535333438 +32633831623531373862656638636564393861336138623263653962633963316430366137313066 +34393332383437353234346332623963346338316537313739333931646465613930373962326230 +36323165396236396236623137386132366332636262363739666135363064633561623466616433 +37626634653437656334636364346135343639363736383963353961653331646165346163306234 +36666665303835326464643665323737306636323536373365306564666232306264373865653439 +65316532303066363164616630656432343036393233396635613033323866303562396235613338 +38613038393035663232366632333131663339366434663661363831393832613834636433376333 +32313536636264363338316265343666323861613162623738366464623332646463373734323364 +30656264303462656461656333353361333531376363303136303964313164663638363832323462 +66336133623238356461636332363136383035363832393366663865303166306431306632396539 +31316463373665303830303233613330306435316137653662663938633736656637323030353133 +38666661316362393237633533623364383163663935346338326331636162663736386134373435 +35663731313937393965346335393164366136616538333830363631613661643865636234373336 +33306265323536363864386464643832316535616132633337303062616636313234363435626331 +32636361326539353762646631633164396535373863653639333134313937613636393734663738 +63396662626263656130633631303536666366323464333433653530613031646236323764633735 +66343034336639666634653064363237386262353337326266366664313934363862303164323832 +38623636613262656638313164613433626531633234356365663433373762346264323135343661 +30333239393366663936626338393137373530623465636630666338396266346161393533646563 +66393837303139386533656363313333633664336363326366336432373334623038356165383438 +36643536376530626137323035386630373337333239333238623230633135623133636366353930 +39306361326436633261373730366562646261356238373765366136333535366565613033333461 +35393961663937333864346363383131313333633063623063646362333962666637646562336534 +62386562613537383365663763356633343633353337343932396362643762373562373033313463 +36363965626661333133636233343239333166316366373561636437326561356361313034653436 +37393232656166663033613437343866346565353538366439393739303665663139613735613563 +37376562343037313634613837383333666133613766313264316132323966623162393366383637 +32303932383435323336366532386139326166386533316338666433623834373634363436633264 +38353031383133343961623133356131336135373635363361656630313833316165356632613861 +64343337663534343737346531656563333663613262373536346431333962623561373336316561 +34613936323935313435623033663036366236396566396333393432303139643635353238303630 +32306561633461646130373933376634666230616532353965366666636162313235663530623763 +33336666616166636636343764643734326439333465646133663162633032383235353132663037 +37386233643139646236383165613736316234653833663335613635643132663839363864333732 +35383365303062383831616133393738353435316233363165336466353533313564396437613961 +36346635326430303938303234383036653130626639373761386166313732363534666463626634 +35303663376166623265363336396530656263303466363533333233633136623130323164303761 +37646231346438333133316232353036386361356538633034333139653335623365373634393639 +35393062393439366634333033396637386264666331383263656434653031656538366265333833 +66326332663932303338636236356164343636383433643365346630333762643362316339386163 +34323236663161383632636638316331663361336564663236613564303538616536373832636636 +31656434376164373330323662663766303764643630393133313530326565653566323535336663 +64643831373363326532353565316336353130383964313664323964336634336662636635646434 +35363339613664306636323235373162633539633864383036633064633561373433393936343661 +38316661373731633033363831623239363634316262393865626338326262626161366538393533 +36613139383266636165393562386430346139366261656664316135353662306361633733376337 +36633435633837643032336466396635663438383537636464373934363064306562623032663032 +62383366633530636137396362326434363331656239643232633563663665646239353535623766 +35656465366432323161306337313465356536623437316232313836653565646362376161636461 +62346264663232333865326639376435316165353836643664323164636262356361353733396334 +32356362623165666464643138656431646231323865373266373137646132643766326230303731 +61666261323738623530343266633364656333383364333136636633636162633362343733313062 +33386337356262356439626632636539386262323437366265663265376439393636656666343266 +35363838353835643337303732373263333639306531643263313961653864323861313630623266 +65386434323963313062393035666537366164326332383263323463383266373531313133373030 +62353931326137613636383639656633313338663666656366643536326364353162383832303734 +38353864343261663864653131363736376565636630313833353964643433303237383837613932 +61633061316266666364666464396434303938393035656564306338636133306238323738633236 +38626538346361316563353837396536653135393463623465616430316662336630633031393064 +31383531333831663138343366346436366463363165396436643166653939316537393633633562 +63626438623138313965303766336134393538373632386161306633363566343434353437396633 +34323730373563666339333232623538376633333139393231323138376130353830373866353831 +65616264383861393536343432353632346234393934376464623235636665313463376230643632 +34333361666430663137626563356633616437613662343762636236353935343833626261663338 +35356666653839613131656266623961383763353861303438393632643535383434663938626139 +31323830393531333032366537306439653830613062336466303935303137653733646363386233 +33313035353731623938363736666466663537633763363965333565316235306565333038663232 +63333363633439333834663436336133613661623066393932646432623961313339376666653666 +32363833643939343437383739643163303538626162613161333230643463306639623331383765 +36333361346366643837376630393562623739363236393465346462343664626339646636353365 +34373161306532396165653438323263656362323935346438363165346663363734363765613530 +36656430346364343632393462623236396136393466636133356639303037323765303866636339 +63373663613637353636386434323062306637373838663939646533356265376238633439363739 +38313534316434366336353938633031646365393939383537336331346466373062346565383430 +38336330373432386266353136633235343036376536323235313963313038663434363431663532 +62623134343764643161353463366662626365656337393037646161303963653230366139333436 +64363464663236326533666666336237366437333237313034666166343836613662643762626233 +30333234343535373838386632663062623533616666326632613633346262323733323666313932 +62616264376566653839643736653263353364383635343566623239343336306532643830326331 +63336264373639396532363639303338323066393233333766343065316331626530666434653932 +34343532613035613861346634633932316533643736336637633336666134313963656262373864 +66393933383063656135366663613532353362323836663430616634663931666235656563383933 +39313764343336636438653731623139333665323262396138393263363836383235613738626237 +31306137306135306237653834613364663962373230626533356633373964353664313163633736 +66643439333730383064363365636361303836396539323761303139363135366131383766643333 +32333465636635333739366364386565663136643461356561633939306566363435636633326235 +33646138613939313332643462383533353935306564643262623765353536393239363839663434 +39383963343365653965316562306366376462316164383839666263633730313339383933306563 +65653332653061626263636137616262316331373065646337326261383966626336313538663433 +64383739653034313866333639336435633134666633656161353733383035393431396433623933 +32356633616634363939613037623763393335313635396139643462333937623133376231313264 +30393731333838303533646238393831333966316566386536343466316566653965306463303137 +30306633306633366364623639303766366266646630653837363238326437643930646361613631 +32636563363336356233613763636234653263356166333239363064336161653733316163616130 +61386639336434353936373232623766313237613962666138333332626563373563666237376261 +34653364373535303963343136313632333733353466623263376661633763383136333766323865 +37363464393165336664356661333433333164666232326239376462366165393362366663636638 +32643330363134653739346332633236613832353862643937643331386434313164336438386533 +65303932323862326164303365363634663434313037313031656662663230393263316464376234 +34653634626263343061353330373032386233623330373266663236303361323233623231366464 +36393765303161623666356534633562646262356432616534373734313832623735643963633637 +64323833326635626531663562353635633166353465366564316132666563303833333235393535 +66366437346562376532363930646238326435376637353161346637313564636231623337356365 +61646366663630393039663631616135326161343130626636366137336530343266393464343433 +31626461373233616237613438373330336261363664633238663462396238616431663535376633 +39373361636336346664643531633331393437373535326665666537323136323437393237356262 +31303137623766616437663337663334616266393430393832626132303435333633383161623930 +35646634633038633462383431316137343466363639383830633430376336313834313437333535 +35356438383661646134326364313062363636386363333361316432626237616233626566366538 +34633162386432356632346438323436383435376631313637373936646263343465376430373239 +33663065383461333165646662633637373231326630343764393966383931366463353261373465 +39666462313536636238303533366165653634663934636664313964666563626636376435346637 +34623333653062663138666237343735643636376232396366306633643134356162653566323664 +34343537386233613063336332303430366462633138333738306236323436623734363465393331 +31396138346535613461633161633262316162353339333335613930653430623562346437343531 +63633731373632396437346164306538653834653432623737373566316539333232643563353261 +63316261323133643731393066363738353166663133363937323634366237633939643835363931 +35356232663130666238386335393733396166653864323564363830383065636564316238396333 +62396562626261363037323562303839303465333765323538326464306435636530663438613765 +35393935636565663331353663356536333966663061306532633234336663666237373864656635 +39343235336335623133333234323137346634303164373539386166613465303237396665363466 +31666462643566363636383161623136626263313437303434643463326438653438613735353139 +30633836616639393732653261653138346638373039316138393363363837396639336636373738 +63356631306165396532313332353861626438356335613334393666356130653134383336313836 +64663531646634363534346230613564323462663236616166306432663963323862633233343937 +62316166643263653665376133636664636164386334336233356365346134386463383162363336 +35333866396362633934623834333938306138373632306361313965623963656133356139616332 +38303931356236653264353236373466333563386561393262343963316634636362393334613931 +62613766366436323239393863313539646364643330316338303637313165336566616435383433 +61343864656661343630373439666538303338633433376630633739356232306235316266336531 +36353062643036323266356139313136636439393239623735346536356461633035336234376364 +65333533363734386461353432643163623633646638623335383030343337396537616138666634 +62626561396436303664363164646639333433346437306536373964316330323266386133643032 +39386632326632353061313130663439633134366165666136303234623431643361333930626266 +62636230343536663833326563633630346266383763643234373239323464373335376530643865 +30336431336638643234633163633464346134316132613366343336626563626436653737363063 +34623865666330396466323833383132626436353130626435373965336366666330336433383166 +32346535326539373662633866613734636430323563666335346665333166373264663234396236 +61363334393062333539383361303035303431636664373839303438613663343662643833363836 +33366563313962666132346136326633613534303865613135346635303537366465353835636465 +35396535336430333437643339323835643036643135353134633532353139326530613739613765 +34363666366535663865616435653232383734393931393432336162353461353332393533613535 +35656639306337383530643561623036653131376162623963313335356263653635316461343062 +32383561306631323461356462393664313964613333623362613732333035373939643539303461 +39613038306161363637613565613065316565363937376539623433356535393331333062666437 +63643437616662666635346633636261396337613735656363366131346465333534346333353431 +39393465363831333730386437366438306465343134393334656462656233646636333564333137 +34616438616465306232383734633038643235356566626431376366333465333737353463636532 +35633836653038383539323535366435353836653533363365636666356236363761316334666433 +35653636326433656338653434323030643839393633303136616261306339663762323062373634 +34653334646166646565333961396530626235326161663638333631313666653865663733336632 +37346538663363306464653537383135363836363931623163613131386434373062323065306265 +32623862386332613332643663623730646239613465303431323636636630323034643430373735 +32373566313763636533646338303830313364393332623265323837386536303232643839346162 +37323039373338323663626133333564376231343630383930643034643135373139653738353261 +32303561626166643466336237366330303566623438363637396363346632653065333232363036 +37306334616638306339303731666361663261353936316638393763303639383739363138616630 +63383834333230323564346531343739626530333763666266316264613864383463303034396265 +62366330663739613039623539663464343938343232306266323066626436316535373530306136 +30383834346132383266386162633230313330396565373231383139363134383331663862356532 +30313539636435643461346533366239393630343465386132396665333436316665646233313861 +36616661663936376630326364613961646662303034613331336665303061346463656339623033 +32626531376361306331613661333139373864353633613333356433316334643633643263616136 +36613839646262376439323636653134363236366665373532323763623864646163363062643966 +36333961663364323536343636656337346332613336643537353234663638656438633136323833 +38653239333435353131353438363861393337663038343236376566383465646534653931626338 +32393863363664643936383135396233363733646662373031373030636133353366636232313334 +34363261306364333637303236646434363566356666316434346336376634316265663838346462 +63336437353065373131343237396666303135323939646366346335316666306363643532666465 +33316533366433643735656364623130663062396331356130623930626131633330663064386263 +61303965393935356138623662633636386430363162303561666333353135363165323233373237 +37383234393130633564666461373262623864626130313764343864616561373030356164343062 +36616239356532373733303831623933643166663432303130323637333939373837303236393134 +62303339663466316331353732616332313631346135616537366135393731643431343131663933 +64663561623039616338383663633530373132613937353666323937316230653265343433636239 +31663730376634336533656133643433373163353063653862373963663438396535323564373264 +64613134616230343363646436663635633062623261336436663034383363643666366138613536 +64343863656264346639383861626332633338393764663361643835383136313264386337376537 +36663065313465386131336530653733316362356634373333376530386239316335326537313739 +66616333343861643632326566386333633165333639326132643963393262316238633565653731 +65373539663962666564643566393133383831326564323634383833313962646565656235653134 +64366563393433643530326138336263333836323261656230626334626362663237383236636430 +34633033353635623062333035613335656435333663613937373965303861613337326231376432 +35666533613866393039376439326330643863303966303737363364306563633365373864656163 +37643338376533313235316362303935356332303430323837623461623739326465653431633733 +39373362396162323730306462386261376434343837333030373230376430393163613737343934 +32366633616561316434656535346365303865393864343236653461653731666438333734373031 +61663631656232653139623736653833333065363135393732316438646462366461326538303862 +37346363663437336433323666383135326161376463393135306565656562303534333039313063 +38363666303665356464393162363861646433383137386435313138346439323532643331376333 +64393534646131663135306138623231323764633664343765303363326337353536346161386166 +33626636626131663436643335366163643436646266326563333434343063316166396233393530 +31623937653138356134373065646139656164663339643862386161303666643163393765393166 +30333635326261333437623436363737616330316635316635373066663261663062663735393038 +63663430613163623535353566373966326162306236646564386163616437303263616137363333 +35383364656662623939386365333139356163666130356133633637356364663466643239366566 +35386334383837306339313336343333323130653638646138363831396234616632316538663164 +30636230373462383536306131656661306366643738636630653030326239326165386235396133 +34393664363533373237623963623634383662396533343262343332643362663261313161313661 +66656137366534333635326334626439303231373162373165643037663833306435366363366464 +31616234613566353362373838643232616231353865663361323862303438656363313362363066 +61353334393835383032343066616334363138393937346139353463616663393633343035653236 +35663864396562366163313165336330643335613534363539343637336530626535336535643633 +32316631616531343865643464313334366239653230636636626136303530353937356236343538 +32363332616338366537313932656262386234343636303666316365656166623037353338666665 +36333332336333663061346635326135393166613933336433313239663864653636346162316630 +39356539316333326363653861353062366138626531626330376165393938303864653632303166 +30376461623861346234643536323132623163663735373062366636633532393165393166393262 +63653036306630373266306665663763656262363261336632636465666230323366626331666131 +34343938366534386334373238383265336639663239643937363631303334636337383731666564 +66336564643865316338643830356232636630613465386135616436396563343233656439633563 +62643361313761626463333038326533666138613965613761633337363733363466383234636434 +36313564323434303738316337663461333532653261363737333966623266306139353164343861 +30363236303437316632346636636665313936383466353265353431336361646363313130333534 +39336530326236636435633133313236636333396131363430326533326231663938316264336139 +36363037336264653131646137653138343731393638366465306161313838353363653865353961 +63313566633366666536346635313432633633366634363538353633313561356139396662633439 +33346164363364323339366362633065666333313431313235343465346534636238366330346332 +38336230316533303262396562363838646234393962303636383564373038636461323939643232 +64383530316333306438396334396263386364376566663038623061306566386166663934386538 +61313466663732396235666430326662336361663962346664663336393739636661666339393363 +33343832366530636232623137306664333766376632303539616137626662646366336533626530 +64626431613032353735306561333338343839306438306335356564373661393164346661623066 +62326463353064626634396531363737383035633063376639666339633334306362396435636135 +62666366373239636366346238666133356235383165363761663966386235343436386361613031 +65613266656133326261636532366631303939643964306338646162313234653238326465393739 +36333430393139643632373363353766393036663033373639323237643863353862386130303433 +65323561626133656434313535316634663435643266323635353136353638336164613039343634 +64353762323339383365313639613137366130653336306665333337636134343564333734643464 +62383638633037383838333565633937613339376437333330613563613431333535323662376434 +31343261613438303663626663623465613237363336306438626539333835333566653665336537 +35303036376534656330373831366166333034653534343261656333393033656530396261313439 +63663965383039313261323132396132666330346239623465386434373231323236383239663739 +62393539376237616632643066623132316337323730383436316634623337353661333037333436 +37663762343461336332383638333165666235653130613332363735373665383563323431383361 +66663762653039363662643265623730356530376539316237636161333534396263663464306266 +38306131393036356662663861326139373766653365663864653163346664616534356430643636 +61346130643630316634633835626465303833613565396664363436333938613366383464393166 +34666161653530653536303839373665303239343938393333666239343135613737353337313832 +65373636633033376639636565386364653564376662393462393332323538323664336535613339 +37353934386234366135633966613765353964346431386562396339336466626264383432346161 +35643738656263333233646330623461356633623766353538643737326261336361373637366434 +36623235366365353966646630303366343430626632343663366461313736396331363861353261 +39613734343134363034643166616666643737633462636330353734376133316266616431633863 +38313566363161666462666536613931333866373263386336333136633064353334383831613462 +64653839643462363739323433623436616464303035383432613133663164333363396537643635 +37636432623138356331336537626638663861366237303063383637373264313232653664306365 +38366461633062366238653931323161383065636638383338313936393235323865623665653865 +32666233316531666138633665393266633831326437653762663066336138383366323233306436 +63396338643966613236346532373432626531343139396463336665363765663861653637333439 +63346234366332346138613036306566393363353532313738333837393564373230356534373436 +64383434376361386565303430343336346165393361646632393938313261376464616461346166 +33643962613932616263363932383261303736393233363463633366653832396431613266656635 +65343265393338306136623064636432333231373132646435653161666434616630393062623537 +66386466613764666635663938303732313562613833343034373037386663343235326432663565 +33616166383934633363633035363738373537353066373233666662333663613339613533373039 +31393533373133633938626262613131613536333133383237373534633331346362636261613033 +35643936343232363733346365613231623562326664383338346535383333313662646130316233 +34343633633832353961633362636261613931306231663236376438663564323564613637663834 +34316332316164666264393333646633346361323236333539393331363834633562663330663764 +31393261643732393835353261326164333461313836616362373562666531613836313562303464 +31623932383733643466396563346632336266386235393461323033356639343734386464333664 +62626135623566663533616261656663383730356631653231656161383161643765363632363236 +63326538636262666438633432323433393032326362356330396165313633366539356630346361 +31333164636166356263356634343264663761376335353938636265366239383166326633306562 +34373964366134313834356338313365393335653639373664393135666639663761393664343932 +32633435373930303031373762393230643065373265656461313039313761313363306234386365 +39333633393931363165666437666636326264306233383262323930363265613031643133306637 +37323266353635623864323738653032356539323134656335343139346437383934336166386232 +65666532616230396563663861613134366637663131316136333636323064396463356334376236 +65336362636234636165333866613664633463366336363563303130363530616235346337313164 +61373165343562653764373563316164333865336532666262346261633838343066343734396532 +34616663386266626363393062346261643333373861366465646631306663313666326230306532 +36303662313061333663343664323863396332313763656463653465393239373263653962373164 +38623130653063313163356136333462363537366236396262343464366531626365306131343265 +39373937353463333064306633616565353663653831626365353562346236323739363363643939 +36393430316635366536623233363862363439613331643962626330313939656662656663393031 +32656630653834663232636232636165336238636261616132333161343364396536643363656638 +38306261363839343263663461613163343361633237353030346138356631303064636234666566 +64626337613530313730336632633164616237336363383565386266313362373536373062623934 +35623364633331396466663238646330363536633763633739623966623437393566373063316265 +35363933623234373135623439326463323738346437326264316632613236666634353939366233 +65383065393834613130336633346161623136326539653630626566353835303634613064393066 +35376138303235636638366461383634366530323339366436633766393338666361366139636165 +65376637353536653261656330393539643232663033343533306463653639666435623332393738 +34653738663566636163396632326464643862373661333139373234666637336238656532613562 +61646165303464373133313365396262663132326631356230373435363465316631353362343636 +30636434636234636265353031653365313538623238326666333466353639366439613231393736 +34393838313334346561366539636333616234663762666663303334613134613265663132336561 +36336438626532366465656165346363343633373961373962306538643362313633343337356166 +35303266396139666366626530313930303936613138386436613136336337643765396664386565 +34326436316433313530326435613036393536373737343233653133653164623336373434373433 +39316635346530366532656365636539383262336436326165373662303331376339383535333430 +65636531333431343764633763316533343639333530306139616266316435346537323564393438 +65346336346131343432343433393464383532626132613064666561613166346434616538313462 +64323738373463383336626539663534653962336135376432303031363865336638633035666163 +30353565303062343165653664626135633064346165346163386338363332626562393761653566 +65656635393739613666356132363333323534346137366461316131313362613563303234393365 +34383335346631326530366230363563616662323066613734313362633465613466656637343538 +34383430376163323230643735346562333531373537366664656138363761366533643030363336 +39666266393361353435333834373038363866373638323862666637353138633530653936393863 +37386266386263616631356532343165623933316230396536643836303062353136396534613562 +61336665663861666136633865336534333037626539633335333836656133396436353063653032 +36663233346530323330383732653639336231316134386535306338336134386236636433333963 +37313731333461663433366361343862613165326430373032376630363838313939636337633632 +64636433613831366636643537643038343133626131643263346666393631323738326339303533 +63376433373463663733393062626636353931303734343864303133363033336235623130646161 +65653936366466366261316430393565623636643565306538666435343137333466396435396136 +36643135393663383234383437343635323331373435613061663062626664393065313338313264 +64333830633937393137353164643930313931373534613961653034656363393466303963353636 +62623932623961383465363131393036386439333834333236323139663965643234393236306238 +38656665373666383131306364306331356563316664656663346263343136316261663062643433 +66303865376261623134616261373336653666326136636466386264613536373762363537363936 +30303133356231653366376433376436663565646135386565643332646137353230366464613337 +38626533303936386431613866303934373563313435343436643334633865303264333961623435 +32616464313664306639623435613331316633613632613737343232366261613464396633613062 +66326238303438373563613034363232346237653036396530613837653961303463336232383038 +63363032366139343431666536393663396130666263316436613236653837393561323466633234 +30346336373634393633613539626466323362333333386366393233366563303764323263353335 +31336639323132623637613035383463326363333638393936383838316235643235383835636164 +31336637333961643535616237633137313439636637313531663035396333346261633733336131 +34393065643861366333353232346566346233616238323831323937323434626161613461313865 +37666463653165613365333866343462353966313237313438313030643437343565313438313134 +65616163653762346264613835336437386534346165626564633936363739386130313737326634 +38353462396134366134316630643235396539386433316636393330306131636662383563383939 +65613765643563303463653764386232386234666162613530633731363731356433356334383438 +35663435633165643264363837343166616161616636643264633435373936303134653666656365 +65333738343265666232346239376631383730303164663664636336366634646533303662643433 +30666238303430373836366463333634656133363931386532643437346437353639333436303862 +63373936663263373666303834363238663430643238666237656336613266653236653432616232 +30323437653538306330666136303335366163396263393936386637333233313934613738633030 +31323166333832393734353264393565363462313066303164633765613630303963643962313262 +31316162333566643232303633623962616362363762316664393337626432393633383230633061 +35373737373938313366633633393339396238393537636565373639316234663162616334303766 +66386634386532373839316639626437366533616238313461613962366632643732333638353166 +62376333376331336537663061663230616430343030323437623133343632383330343466333263 +36643331363966323138306331303066386138333464376134376565623433313264363239613965 +65663062616438333334636534306138336234356237343833643135646263636332346132333532 +63303939306361393437316162646539366433316638613035613764376337653235346134376139 +39623338616533366534613435303537356137333235363164646634323335356338623361623566 +62356264333739303765356166393131653639663636323061396237623431666533343135383863 +31393466613734333131393739333465653239656238313963666563393261353032623339613964 +36356534366561633537373234396432643334623662626132656265306335333334376161626136 +36633532373164646133656539363037633361333637626261353865373739663166613664373265 +66636637316130353164633163393964316566663463316130316138373434663564313036323736 +64316661666461626263383261636462666236343836633236376137323437616561636238366237 +39353664373061613465373064633337353431666263326164306263363837616565626330383439 +66653331653036303637386665356464393530376134363662653731336131613664323731383965 +35626335643038323065616130326263386331343732623833363762313330333737623661633064 +37303934613031613031633238306466336533663936663238396166303731653535376361323038 +31333137663966633763643038633762303339333532396261393961663665616465623034626536 +39653537366332333131303735336466613634393965363938376565343435623465643733386137 +32303630633766633066663339316566643364666265303830396365343839633162383130353766 +39383738663830303866323862303265316266353539626665353130656366376664383338396233 +38613437393439663833373661323964313635646639306537373739343637376435353638363932 +30623131386130333530666163616538623765663830643239323333613931356635383261346436 +37336433353765326633386265306363363436626534303533353165636164356338613866666462 +65373135396364633935643261343535383062633032373161313639656666333638623634646464 +39336661663361363264383763393034346262366563663339373432336433306663303364333565 +31623265393737333030396162396335663666366561633964363532343437353161613239393166 +32623333333365633937346364613231323663366334393862643034626536623766373262366336 +37366632316238363266346635353233326539656539313162313065663265336537353166666331 +66363461323962376262316635396434356362333237373130363664396564663561656362346239 +66323236343734356338306264346539353435653639353730333064363933326332666535623763 +37383836363536303036333339353037313861643432646661666638633338663437353332626566 +62653831646438326237373265356238613763643061656365643563653436383637386362653362 +38303865333135633434646139366664393633396566343739643061343162626266643836316464 +35323866366363353162616137616564353434316139363733306166393762613732303335393066 +63336433643634316335326139376462613536376663663634396361646338333335656632666236 +35396633363735613435366238623161646561366333626233326635643932353335303235386637 +31633031366430336238396137656135643961323462626562633132336164656166636533363862 +62353034363035316630633031663266313861366663386266656138623935306339356163306332 +37643966353163323338393138643462366332303233303866633233396334333237323431363065 +36333038386239353231643334636137326235366537343934313435656433666534323337356166 +37393835613038386565623433303561313062613363386431626535346636353264616532663464 +63373863633765323466386432393065653830396363396465336331336334326361613137643365 +34613233653834633938353763633232323431666133333731653133353530313564663030363766 +35313230323264343863633864626535323232316138643563316536366531656235343932633761 +38616664623238393039643466363839363630626234363233376465613665323530623366346430 +36633363613132663838626664353539326566366438323663623065653631366538663935346638 +32326431306338313062626531633762636330303864356437643066383838383863366332323732 +38656633346464353763346265346465353761313438346332396431623661323565356633656537 +34393331353266326364613866663566363830343066313262666266616664343265383866623439 +32366662306335643866303134376638353066316436636232633265393061663233363661366165 +31643539616432386235643037343534343662373464353465643831366236366231376633336139 +37383964663034616333386139343339313139363061326662316365623734323065626433663030 +35383934366336353437643061636566333634363239623461383066663365326166316630646462 +63646438376539336336666564656230663637323934373737613161313331393134396234646365 +34613238353765383865613736396266653764613632666338336536646163303966393764326636 +38383436376666343965383731313833313131643636656536363438383433323165656238306463 +65303963376264653138313065313731383333633530626162313932376335623330353239396430 +36616235353163356132336135646639303639303961663731376435386635633938616238623433 +35643237613337623536616535343534366534393165343366623034623065356335313835386566 +61616663346663356338656434666561386431373433333637333330613135663635633736636364 +61613333336330643231376530386633306433633138336136356634623137326565623430333135 +32633238393538623433 diff --git a/lmn-client.yml b/lmn-client.yml index 5584d6e..4a2fab7 100644 --- a/lmn-client.yml +++ b/lmn-client.yml @@ -49,6 +49,7 @@ - lmn_network - role: up2date_debian tags: upgrade + - lmn_encrypt - lmn_sssd - lmn_mount - lmn_kde @@ -63,7 +64,7 @@ - role: lmn_localhome when: localhome - role: lmn_localuser - when: localuser + when: localuser|bool - role: lmn_exam when: exam_mode - role: lmn_wlan @@ -80,15 +81,17 @@ loop_var: rolename when: custom_roles is defined - - name: Final tasks - ansible.builtin.include_role: - name: "{{ role }}" - loop_control: - loop_var: role - loop: - - lmn_security - - lmn_finish - - lmn_tmpfixes + - name: Import role security + ansible.builtin.import_role: + name: lmn_security + + - name: Import role finish + ansible.builtin.import_role: + name: lmn_finish + + - name: Import role tmpfixes + ansible.builtin.import_role: + name: lmn_tmpfixes - name: Apply roles that must run serial diff --git a/lmn-vault b/lmn-vault deleted file mode 100644 index 01cc8c1..0000000 --- a/lmn-vault +++ /dev/null @@ -1,107 +0,0 @@ -$ANSIBLE_VAULT;1.1;AES256 -30323066396237616634646638353133663731623734383863373431363930356262636162323264 -3737353636623963643737353762663064663935306631320a353231326664353433633339363733 -33333038346638316335333534636163333564633137663063646334333832633935323763336633 -3662303830303363380a663633643139343630373838383337346631366539636333346666383434 -37336232376466613665313934616537313064653566353763613161613866393139656165363835 -61336131343162313566363562303464623938313036396463376463636334356561666136666161 -36333131663432336238303831626137323635323636633966336639616265656637363432393436 -65636338646234363863373666366131333333356166313933376331666633653132396161616661 -32663932666531393066623935663462353534373666313465663034343438303331303632633863 -33623534653031393431646238356135326130643362363238366666306161353237376461356338 -33393738323338643764356363646530653938313633393730323036323030623236643133396366 -31313837336438393035373936656662633330643933323039356539386133653764326639343938 -38323863643338613564633964646432306664353163666231616135353235616233623632623564 -32616636376539303132376130343966666261646434626366393262643131356230353937663530 -66396235333839633461323139663431343634633634663865373564613133633465353861326430 -65356163653162363237303839353930636163663136393831613964306334663863323034336333 -37396265666538316630333937366234366636316233393430353334633433663461626263346666 -61646532613562333663653162356533356465313764363032666166366365636465653037343734 -39613730396262343039373433346237316131343832656539346365383133623964383764393832 -33333138386264376161653261656563613738643563663238656562333066626137656164393036 -62643938656138356134303666353332643263643238326137386264356632616138613436373331 -64653730663332393964323831336332396233333031633832643564313238643334303132393536 -31356633656536306237346366633461353661386530303663376133666562346565356438323036 -35643266646136373132653537646138356238306130613034656539396230356633386330333933 -34393435376266666361383164666266663563396466393239653362663232366164376137376166 -33663634313236366563656537366535363264623861646564336466363665343433383532666562 -66326332636536363836383135343361663636393138623362643636623533363931396563353261 -66383565616432616361353338303038663730343566653438336661656431303837393464643466 -65386436396132323261313361343164393163303830653736626637383531613432343435396630 -66373831396264646464353565363633333666333361386639353165643566376430653264316432 -37353163323337643461636331646561313465383032383761373665336666303535333363613862 -66386132636133623263366436326131666632623238356530396361323962316463666261353137 -34366266303739613462386235616337383334633234336261613231366131316535373866306133 -61356438356235303335363638663861383332383931343032326238383536623437313039383639 -31663632613135383037313032623064623633376663656634323534373463343932323964313464 -62656134623836333835633061626331623461653565336438636431306434323638666336623862 -63343835623661633534646437616134623962323139363265306462656633653463616366613232 -38613830336639316139643732373938396435363966663330366335303232666563303633633463 -33366663623062393262323530633163363363343930343265363430303130303436376664646431 -65303263626263653865343161363064386163323636663264353539393031383639303835636461 -32666462373063346431353732346330636432643534633538316638316661393866303039346333 -32623637336434333836303936613066313562373834653338613139326337366664666231393863 -62653333353736383431383534313164346639663037643366333931633539343137356464643236 -39396561306565666262303337316532623564653632353533316235643732656336613730643361 -36303761346165353561616364326430343763323966643238616630643639323639663932306139 -63333733643536376132383236343937313639623763663161323835353333313838346136386533 -31383065373030623231626533343333646339643231373936663336303834666639623431366336 -37653361313161393433363039633139373338346230366465343261326535303331616437396264 -62356533636436663532663233353938623265663139376636653532303561356130336630393432 -62646331326163366336373164333839626666636335303836363766346264363931626161643039 -62613139306634323162613131393739373133343034373633353532616637373666613131326337 -37613437323132396132333030386132613538313339656234366435383561656331326238306563 -61616133336365656662333064326233313630646633386138333533386435356262323737316335 -64313862366533373235633161363139376638336331373163653762396666373536333663313963 -34396134613633333631653930373965393532313038616331386332376432613032653537356334 -38636362623539336134613832313065653539646366343430356431653361333662323334653663 -61326561313433363561633631653039386662383766326136363266353536393063643532363038 -35613866313634313434636463663138636165356432336234613032336635636263336439313061 -30666639316665353733653338376162643338316533613632303433646239663138376536636330 -32386234626430393833666263623135386561633230326664313137343463336631363763643931 -39616139396261393366313736636265303466333533336430663439303239373963666333613537 -35363138653831653435626132383135633631386462633038363966313838663236396532366163 -62616165376635613164326439623563653037616638383032326339346230663935376635383263 -62306532323764633631366535383233316335316439393539313565306465353365343636333462 -62616231393035646235643734373764326334643366613135346433653639303864323464343034 -31303161353963663839373565396466353033333165316134633936653161346436326362643534 -32366665633338323130633737613934343031323766663164633134373464656132303735316337 -66663361333136333839653062373133343761386439323463643336303137383932386665326136 -64356531353933383235633039326266666232303764326338366462653834623736336362653233 -35353963356231613539656630623334663763313837383261663163343266613463613366666430 -66396534663531633261336162366436333534633461636136643230336466636265663531356336 -62336565646234303765323866316562396561316464393636356262313663316437393634656238 -63613530303164653264373863336238646666323938303631366162636265643161616433343232 -35343638396437376337306262643161626234636338643264396362653836653337633632303166 -65663133396462316466663038346565623132356631343865613462323035666537343134363436 -32373539303763373134336534643930636234643338376536376666346561393731316666343364 -36653561303563646233653865353736356537343938383930336130623964623866313539636335 -32666536396538313032613939666632333839303062386366353639613862653134323162643533 -62663131303233323666353336363461646231376163343563396463356634653532633266306433 -34363930656562366563643937633862646565393930303537626338623631313436613564616530 -39353663623939313235306231373537393535326238623038633232366131303730333838663838 -65366437333665333364336535303434383934663532303035313639646635653833666566383163 -32666334373237326266366337353636636465613963366538326362363132653466333634333534 -63366537653866346133353635356332656164336632333465316363376238653563316661386132 -64343063306663376430363163323161336166313762613066663061346236343731343836643731 -32306365656534353733356561373561386334373661303530326332333061636536363364386233 -63313035653166313164333537313662636136613565323433333738376237626263373538336266 -35646633663165396366613162616338616532383437383630663061666338616131356534656636 -36353036326533316339313833356466386163343065653037363038303239643361306335353262 -66393361363936373630326533306164366237353161346335303136633561363265643135363165 -63333833656637636635363931393965663933396265643239363939363337396666633366373233 -37656630376262643836643063383762623331653761353030333736366462663964363032626536 -63363136343464373230353330313830653730333438393238393232353932316337616636356138 -61326638613433666131643830323565623466643333373432323330626265326363356161326538 -61336537666137333166333439343535313135323438376633326535343964626136386138633038 -62363432613861356134376237393436356361373839316637376234303566313164666534663837 -37613763653636363231396163616236626662323761353065383535623266616561323733326437 -65666662386163643232613664346432386233643534626335353336346561303032653163346234 -61333164613832386631316430643537303161613161613631363534366166303834363230643839 -34363233656165623236323634313566373166373565353837303162313262333035663738326637 -34313435643630393738613462373034303264653964393563393739386537653836363833383534 -37383937316166333533633161643463353961393737353561343933613830623061346235353263 -64633839396466393361383462636635653464343239303736656561303033386465323036323964 -32356536356437643436396162643334653631636339363161373437666538396430343162366139 -39343564366338363965633139633338376436353230356134633163316362393032653561613763 -6465303166646337336264633666363638643436333466306565 diff --git a/misc/preseed.cfg b/misc/preseed.cfg index 09c6cfe..2cbe370 100644 --- a/misc/preseed.cfg +++ b/misc/preseed.cfg @@ -50,13 +50,11 @@ d-i apt-setup/contrib boolean true d-i mirror/country string manual d-i mirror/http/hostname string deb.debian.org d-i mirror/http/directory string /debian -#d-i mirror/http/proxy string http://10.167.0.253:3142/ -#d-i mirror/http/proxy string http://192.168.1.17:3142/ -#d-i mirror/http/proxy string http://aptcache.steinbeisschule-reutlingen.de:3142/ -d-i mirror/http/proxy string http://aptcache.pn.steinbeis.schule:3142/ +#d-i mirror/http/proxy string http://aptcache.pn.steinbeis.schule:3142/ +d-i mirror/http/proxy string # NTP server to use: -d-i clock-setup/ntp-server string server.pn.steinbeis.schule +#d-i clock-setup/ntp-server string server.pn.steinbeis.schule ### Backports: #apt-setup-udeb apt-setup/services-select multiselect security, updates, backports @@ -129,10 +127,9 @@ d-i preseed/late_command string \ in-target mount -v -t tmpfs tmpfs /dev/shm ; \ echo "$vaultpw" > /target/dev/shm/vaultpw ; \ in-target ansible-pull --verbose --purge --extra-vars="run_in_installer=true" \ - -l localhost \ - -i inventory-sample.yml --url=https://codeberg.org/DigitalSouveraeneSchule/lmn-client.git -C fvs $playbook ; \ + --vault-password-file /dev/shm/vaultpw -l localhost \ + -i inventory-sample.yml --url=https://codeberg.org/DigitalSouveraeneSchule/lmn-client.git -C main $playbook ; \ fi -## --vault-password-file /dev/shm/vaultpw -l localhost \ # ## When installing in combination with ansible-pull, ## export your ansible playbook like: diff --git a/misc/vm/Netzlaufwerke neu verbinden.lnk b/misc/vm/Netzlaufwerke neu verbinden.lnk new file mode 100755 index 0000000..e2fe26b Binary files /dev/null and b/misc/vm/Netzlaufwerke neu verbinden.lnk differ diff --git a/misc/vm/injector.ps1 b/misc/vm/injector.ps1 new file mode 100644 index 0000000..4c785cf --- /dev/null +++ b/misc/vm/injector.ps1 @@ -0,0 +1,155 @@ +param( + [string]$ticketb64 +) +# BASE64 +$ticket = New-Object System.Byte +#reading from b64 +$ticket = [System.Convert]::FromBase64String($ticketb64) +if ($ticket -eq $null){ + write-host "[-] Be Sure entering the correct mode" + write-host "[-] Cannot receive ticket from file or b64" + exit; +} + + +# ------------------- FUNCTIONS -----------------------# +$ptt = @" +[StructLayout(LayoutKind.Sequential)] +public struct LUID +{ + public UInt32 LowPart; + public Int32 HighPart; +} +public enum KERB_PROTOCOL_MESSAGE_TYPE +{ + KerbDebugRequestMessage, + KerbQueryTicketCacheMessage, + KerbChangeMachinePasswordMessage, + KerbVerifyPacMessage, + KerbRetrieveTicketMessage, + KerbUpdateAddressesMessage, + KerbPurgeTicketCacheMessage, + KerbChangePasswordMessage, + KerbRetrieveEncodedTicketMessage, + KerbDecryptDataMessage, + KerbAddBindingCacheEntryMessage, + KerbSetPasswordMessage, + KerbSetPasswordExMessage, + KerbVerifyCredentialMessage, + KerbQueryTicketCacheExMessage, + KerbPurgeTicketCacheExMessage, + KerbRefreshSmartcardCredentialsMessage, + KerbAddExtraCredentialsMessage, + KerbQuerySupplementalCredentialsMessage, + KerbTransferCredentialsMessage, + KerbQueryTicketCacheEx2Message, + KerbSubmitTicketMessage, + KerbAddExtraCredentialsExMessage +} +[StructLayout(LayoutKind.Sequential)] +public struct KERB_CRYPTO_KEY32 +{ + public int KeyType; + public int Length; + public int Offset; +} +[StructLayout(LayoutKind.Sequential)] +public struct KERB_SUBMIT_TKT_REQUEST +{ + public KERB_PROTOCOL_MESSAGE_TYPE MessageType; + public LUID LogonId; + public int Flags; + public KERB_CRYPTO_KEY32 Key; + public int KerbCredSize; + public int KerbCredOffset; +} +[StructLayout(LayoutKind.Sequential)] +public struct LSA_STRING_IN +{ + public ushort Length; + public ushort MaximumLength; + public IntPtr buffer; +} +[DllImport("secur32.dll", SetLastError=false)] +public static extern int LsaLookupAuthenticationPackage([In] IntPtr LsaHandle,[In] ref LSA_STRING_IN PackageName,[Out] out UInt32 AuthenticationPackage); +[DllImport("Secur32.dll", SetLastError = true)] +public static extern int LsaCallAuthenticationPackage(IntPtr LsaHandle,uint AuthenticationPackage,IntPtr ProtocolSubmitBuffer,int SubmitBufferLength,out IntPtr ProtocolReturnBuffer,out ulong ReturnBufferLength,out int ProtocolStatus); +[DllImport("secur32.dll", SetLastError=false)] +public static extern int LsaConnectUntrusted([Out] out IntPtr LsaHandle); +[DllImport("secur32.dll", SetLastError=false)] +public static extern int LsaDeregisterLogonProcess([In] IntPtr LsaHandle); +[DllImport("advapi32.dll", SetLastError=true)] +public static extern uint LsaNtStatusToWinError(uint status); +"@ + + +Function ConnectToLsa() +{ +$lsahandle = New-Object System.IntPtr +[int]$retcode = [KRB.PTT]::LsaConnectUntrusted([ref]$lsahandle) +if ($retcode -ne 0){ + write-host "[-] LsaConnectUntrusted Error (NTSTATUS): ", $retcode -ForegroundColor Red + exit; +} +return $lsahandle +} + +#-------------------------------- ENTRY POINT ----------------------------# + +$assemblies = [System.Reflection.Assembly]::LoadWithPartialName("System.Security.Principal") +Add-Type -MemberDefinition $ptt -Namespace "KRB" -Name "PTT" -ReferencedAssemblies $assemblies.location -UsingNamespace System.Security.Principal +# CONNECTING TO LSA +$LsaHandle = ConnectToLsa +write-host "[?] LSA HANDLE: ", $LsaHandle +# EXTRACTING KERBEROS AP +$retcode = New-Object System.Int32 +$authPackage = New-Object System.Int32 +$name = "kerberos" +$importnantlsastring = New-Object KRB.PTT+LSA_STRING_IN +$importnantlsastring.Length = [uint16]$name.Length +$importnantlsastring.MaximumLength = [uint16]($name.Length + 1) +$importnantlsastring.buffer = [System.Runtime.InteropServices.Marshal]::StringToHGlobalAnsi($name) +$retcode = [KRB.PTT]::LsaLookupAuthenticationPackage($lsaHandle,[ref]$importnantlsastring,[ref]$authPackage) +if ($retcode -ne 0){ +write-host "[-] Error LsaLookupAuthPckg (NTSTATUS): ", $retcode -ForegroundColor Red +exit; +} +write-host "[?] Kerberos Package: ", $authPackage +# GETTING CURRENT LUID (INJECT PURPOSES) +$output = klist +$CurrLuid = $output.split("`n")[1].split(":")[1] +$sysIntCurrLuid = [convert]::ToInt32($CurrLuid,16) +$luidFinally = New-Object KRB.PTT+LUID +$luidFinally.LowPart = $sysIntCurrLuid + +# TICKET INJECTING +$protocolReturnBuffer = New-Object System.IntPtr +$ReturnBufferLength = New-Object System.Int32 +$ProtocolStatus = New-Object System.Int32 +$KrbRequestInfo = New-Object KRB.PTT+KERB_SUBMIT_TKT_REQUEST +$KrbRequestInfoType = $KrbRequestInfo.getType() +$KrbRequestInfo.MessageType = [KRB.PTT+KERB_PROTOCOL_MESSAGE_TYPE]::KerbSubmitTicketMessage +$KrbRequestInfo.KerbCredSize = $ticket.Length +$KrbRequestInfo.KerbCredOffset = [System.Runtime.InteropServices.Marshal]::SizeOf([type]$KrbRequestInfoType) +$KrbRequestInfo.LogonId = $luidFinally +$inputBufferSize = [System.Runtime.InteropServices.Marshal]::SizeOf([type]$KrbRequestInfoType) + $ticket.Length +$inputBuffer = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($inputBufferSize) +[System.Runtime.InteropServices.Marshal]::StructureToPtr($KrbRequestInfo,$inputBuffer,$false) +[System.IntPtr]$PtrToCred = $inputBuffer.ToInt64() + $KrbRequestInfo.KerbCredOffset +[System.Runtime.InteropServices.Marshal]::Copy($ticket,0,$PtrToCred,$ticket.Length) +$ntstatus = [KRB.PTT]::LsaCallAuthenticationPackage($lsaHandle,$authPackage,$inputBuffer,$inputBufferSize,[ref]$protocolReturnBuffer,[ref]$ReturnBufferLength,[ref]$ProtocolStatus) +if(($ProtocolStatus -ne 0) -or ($ntstatus -ne 0)) +{ + Write-Host "[!] Error in LsaCallAuthenticationPackage" -ForegroundColor Red + write-host " NTSTATUS: ", $ntstatus, " Protocol Status: ", $ProtocolStatus + if ($ProtocolStatus -eq -1073741517){ + " Ticket may be out of date" + } + exit; +} +if($inputBuffer -ne [System.IntPtr]::Zero) +{ + [System.Runtime.InteropServices.Marshal]::FreeHGlobal($inputBuffer) + [System.Object]$ticket = $null +} +klist diff --git a/misc/vm/vm-prepare-sys.ps1 b/misc/vm/vm-prepare-sys.ps1 new file mode 100644 index 0000000..ad8f16f --- /dev/null +++ b/misc/vm/vm-prepare-sys.ps1 @@ -0,0 +1,73 @@ +# Installiere alle Mounts aus target.csv +# Geprüft wird, ob das Laufwerk bereits vorhanden +# 11.05.2025 da + +function Mount-Drive { + param ( + [string]$DriveLetter, + [string]$TargetPath + ) + + try { + & "C:\Program Files (x86)\WinFsp\bin\launchctl-x64.exe" start virtiofs viofs$DriveLetter $TargetPath \\.\${DriveLetter}: + Write-Verbose "Laufwerk hinzugefügt: $DriveLetter" + } catch { + Write-Error "Fehler beim Hinzufügen des Laufwerks ${DriveLetter}: $_" + } +} + +function Import-VMInfo { + param ( + [string]$Path + ) + + if (Test-Path $Path) { + return Get-Content -Path $Path -Raw | ConvertFrom-Json + } else { + Write-Error "Fehler beim Einlesen der VMInfo Datei ($Path nicht gefunden)." + Write-Error "Tipp: Beim Neustart der VM wird diese Datei neu angelegt." + Pause + exit + } +} + +# Laufwerk Y: mit weiteren Mountpoint-Infos mounten +& "C:\Program Files\Virtio-Win\VioFS\virtiofs.exe" -m Y: +#Mount-Drive -DriveLetter "Y" -TargetPath "VM-Data" + +# VMInfo aus JSON File einlesen +$VMInfoPath = "Y:\.vminfo.json" +# Schleife, die auf das Laufwerk wartet +while (-not (Test-Path $VMInfoPath)) { + Write-Host "Warte auf $VMInfoPath..." + Start-Sleep -Seconds 1 +} +$VMInfo = Import-VMInfo -Path $VMInfoPath + +# Weitere Laufwerke einbinden +#foreach ($virtiofs in $VMInfo.VirtioFS) { +# $targetDrive = $virtiofs.Drive +# if (-not (Get-PSDrive -Name $targetDrive -ErrorAction SilentlyContinue)) { +# Mount-Drive -DriveLetter $targetDrive -TargetPath $virtiofs.Target +# } else { +# Write-Error "Laufwerk bereits vorhanden: $targetDrive" +# } +#} + +# Drucker installieren +foreach ($drucker in $VMInfo.Printers) { + # Überprüfen, ob der Drucker bereits vorhanden ist + $druckerName = $drucker.Name + $druckerVorhanden = Get-Printer | Where-Object { $_.Name -eq $druckerName } + + # Umwandlung in HTTP-URL + $httpUrl = $drucker.IppURL -replace "ipp://", "http://" -replace "122.1", "122.1:631" + + if (-not $druckerVorhanden) { + # Drucker hinzufügen, wenn er nicht vorhanden ist + Add-Printer -PortName $httpUrl -Name $druckerName -DriverName "Microsoft IPP Class Driver" + Write-Host "Drucker hinzugefuegt: $druckerName" + } else { + Write-Host "Drucker bereits vorhanden: $druckerName" + } +} diff --git a/misc/vm/vm-prepare-sys.xml b/misc/vm/vm-prepare-sys.xml new file mode 100755 index 0000000..b00a30e Binary files /dev/null and b/misc/vm/vm-prepare-sys.xml differ diff --git a/misc/vm/vm-prepare-user.ps1 b/misc/vm/vm-prepare-user.ps1 new file mode 100644 index 0000000..15b540a --- /dev/null +++ b/misc/vm/vm-prepare-user.ps1 @@ -0,0 +1,102 @@ +# Installiere alle Mounts aus target.csv +# Geprüft wird, ob das Laufwerk bereits vorhanden +# 11.05.2025 da + +function Import-VMInfo { + param ( + [string]$Path + ) + + if (Test-Path $Path) { + return Get-Content -Path $Path -Raw | ConvertFrom-Json + } else { + Write-Error "Fehler beim Einlesen der VMInfo Datei ($Path nicht gefunden)." + Write-Error "Tipp: Beim Neustart der VM wird diese Datei neu angelegt." + Pause + exit + } +} + +function Add-PathToQuickAccess([string[]]$path){ + $path | %{ + write-host "Adding path '$($_)' to Quick acccess list." -F Green + try{ + $link = (New-Object -Com Shell.Application).NameSpace($_).Self + if(!$link){throw "Item path not valid to be pinned."} + $link.Verbs()| ?{$_.Name.replace('&','') -match 'An Schnellzugriff anheften|Pin to Quick access'} | %{$_.DoIt()} + }catch{ + write-error "Error adding path. $($_.Exception.Message)" + } + } +} + +$VMInfoPath = "Y:\.vminfo.json" + +# Schleife, die auf das Laufwerk wartet +while (-not (Test-Path $VMInfoPath)) { + Write-Host "Warte auf $VMInfoPath..." + Start-Sleep -Seconds 1 +} + +# VMInfo aus JSON File einlesen +$VMInfo = Import-VMInfo -Path $VMInfoPath + +& $PSScriptRoot\injector.ps1 $VMInfo.krb5.cred +$klistOutput = klist + +$serverping = Test-Connection -ComputerName "server.pn.steinbeis.schule" -Count 2 -Quiet +if ($serverping) { + if ($klistOutput -like "*Client*") { + foreach ($Mount in $VMInfo.Mounts) { + net use /persistent:no "$($Mount.Drive):" "$($Mount.RemotePath)" + #New-SMBMapping -Localpath "$($Mount.Drive):" -Remotepath $Mount.RemotePath + Write-Host("net use $($Mount.Drive): $($Mount.RemotePath)") + } + } else { + #if (-not ($klistOutput -like "*Client*") -or (-not (Test-Path "H:"))) { + $Credential = Get-Credential -Message "Die automatische Einbindung der Netzlaufwerke ist fehlgeschlagen.`nBitte geben Sie Ihre Anmeldeinformationen für das Netzlaufwerk ein" $VMInfo.User + # Laufwerke einbinden + foreach ($Mount in $VMInfo.Mounts) { + net use /persistent:no "$($Mount.Drive):" "$($Mount.RemotePath)" /user:"$($Credential.UserName)" "$($Credential.GetNetworkCredential().Password)" + Write-Host("net use /persistent:no `"$($Mount.Drive):`" `"$($Mount.RemotePath)`"") + #New-SMBMapping -Localpath "$($Mount.Drive):" -Remotepath "$($Mount.RemotePath)" -UserName "$($Credential.UserName)" -Password "$($Credential.GetNetworkCredential().Password)" + #Write-Host("New-SMBMapping -Localpath $($Mount.Drive): -Remotepath $Mount.RemotePath") + } + } +} else { + Add-Type -AssemblyName System.Windows.Forms + $message = "Der Server kann derzeit nicht erreicht werden.`nDaher können die Netzlaufwerke derzeit nicht verbunden werden.`nVersuchen Sie es zu einem späteren Zeitpunkt erneut mit dem Skript: Netzlaufwerke-verbinden" + $title = "Server nicht erreichbar" + [System.Windows.Forms.MessageBox]::Show($message, $title, [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Warning) +} + +# Ändere den Namen der Netzlaufwerke +$shell = New-Object -ComObject Shell.Application +foreach ($Mount in $VMInfo.Mounts) { + $folder = $shell.Namespace("$($Mount.Drive):") + if ($folder) { + $folder.Self.Name = $Mount.Name + Write-Host "Das Netzlaufwerk $($Mount.Drive): wurde in '$($Mount.Name)' umbenannt." + } else { + Write-Host "Fehler beim Zugriff auf das Netzlaufwerk." + } +} + +# Pfade zur Schnellzugriff hinzufügen +Add-PathToQuickAccess $VMInfo.QuickAccess + +# Pfade für Standardorte ändern +$regPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" +foreach ($USF in $VMInfo.UserShellFolders) { + Write-Host "Set-ItemProperty -Path $regPath -Name $($USF.Name) -Value $($USF.Path)" + Set-ItemProperty -Path $regPath -Name "$($USF.Name)" -Value "$($USF.Path)" +} + +# Explorer Neustart erzwingen (evtl. nicht notwendig) +Stop-Process -Name explorer -Force +# Start-Process explorer + +# Bei Lehrern Papercut-Client starten +if (($VMInfo.Groups -contains "teachers") -and -not (Get-Process -Name pc-client -ErrorAction SilentlyContinue)) { + & "C:\custom\papercut\pc-client.exe" -m --user $VMInfo.User +} diff --git a/misc/vm/vm-prepare-user.xml b/misc/vm/vm-prepare-user.xml new file mode 100755 index 0000000..f3f8854 Binary files /dev/null and b/misc/vm/vm-prepare-user.xml differ diff --git a/misc/vm/vm-update-user.ps1 b/misc/vm/vm-update-user.ps1 new file mode 100644 index 0000000..c3036d5 --- /dev/null +++ b/misc/vm/vm-update-user.ps1 @@ -0,0 +1,30 @@ +# Injects krb5-credential from .vminfo.json if available +# 02.07.2025 da + +function Import-VMInfo { + param ( + [string]$Path + ) + + if (Test-Path $Path) { + return Get-Content -Path $Path -Raw | ConvertFrom-Json + } else { + Write-Error "Fehler beim Einlesen der VMInfo Datei ($Path nicht gefunden)." + Write-Error "Tipp: Beim Neustart der VM wird diese Datei neu angelegt." + Pause + exit + } +} + +$VMInfoPath = "Y:\.vminfo.json" + +# Schleife, die auf das Laufwerk wartet +if (-not (Test-Path $VMInfoPath)) { + Write-Host "$VMInfoPath nicht gefunden. Skript beenden." + exit +} + +# VMInfo aus JSON File einlesen +$VMInfo = Import-VMInfo -Path $VMInfoPath + +& $PSScriptRoot\injector.ps1 $VMInfo.krb5.cred diff --git a/misc/vm/vm-update-user.xml b/misc/vm/vm-update-user.xml new file mode 100755 index 0000000..b6500e8 Binary files /dev/null and b/misc/vm/vm-update-user.xml differ diff --git a/roles/custom/fvs/files/lmn-codeblocks.sh b/roles/custom/fvs/files/lmn-codeblocks.sh new file mode 100644 index 0000000..27f24b3 --- /dev/null +++ b/roles/custom/fvs/files/lmn-codeblocks.sh @@ -0,0 +1,15 @@ +if [[ "$UID" -gt 10000 ]] && [[ ! -f ~/.config/codeblocks/default.conf ]] ; then + mkdir -p ~/.config/codeblocks + cat < ~/.config/codeblocks/default.conf + + + + + + + + + + +EOF +fi diff --git a/roles/custom/fvs/files/lmn-patch-dolphin.sh b/roles/custom/fvs/files/lmn-patch-dolphin.sh index 60707c8..ca7efc6 100755 --- a/roles/custom/fvs/files/lmn-patch-dolphin.sh +++ b/roles/custom/fvs/files/lmn-patch-dolphin.sh @@ -16,11 +16,16 @@ fi id="$(grep ID "$file" | sed -E "s|^.+ID>([[:digit:]]+)/([[:digit:]]+) -+ Nextcloud -+ -+ -+ -+ -+ -+ $IDENTITY/${NUM3} -+ true -+ -+ + Network diff --git a/roles/custom/fvs/files/lmn-sync b/roles/custom/fvs/files/lmn-sync index 16668f8..6ae5e17 100644 --- a/roles/custom/fvs/files/lmn-sync +++ b/roles/custom/fvs/files/lmn-sync @@ -12,7 +12,7 @@ fi #rsync -rlptD --chown=pgmadmin:root --chmod=F755,D755 rsync://server:/local-program/ /usr/local/lmn RSYNC_COMMAND=$(rsync -ai --delete --exclude=mimeinfo.cache \ - --chown=root:root --chmod=F644,D755 "rsync://server:/desktopstarter" \ + --chown=root:root --chmod=F644,D755 "rsync://fileserver:/desktopstarter" \ /usr/local/share/applications/ | sed '/ \.\//d') if [[ $? -eq 0 ]] && [[ -n "${RSYNC_COMMAND}" ]]; then echo "${RSYNC_COMMAND}" diff --git a/roles/custom/fvs/files/policies.json b/roles/custom/fvs/files/policies.json index 1fd5fb0..b1c20cc 100644 --- a/roles/custom/fvs/files/policies.json +++ b/roles/custom/fvs/files/policies.json @@ -3,9 +3,9 @@ "Proxy": { "Mode": "autoDetect" }, - "OverrideFirstRunPage": "https://www.steinbeisschule-reutlingen.de", + "OverrideFirstRunPage": "https://www.steinbeis.schule", "Homepage": { - "URL": "https://www.steinbeisschule-reutlingen.de", + "URL": "https://www.steinbeis.schule", "Locked": false, "StartPage": "previous-session" }, @@ -15,7 +15,7 @@ "toplevel_name": "FvS-Reutlingen" }, { - "url": "https://www.steinbeisschule-reutlingen.de", + "url": "https://www.steinbeis.schule", "name": "FvS-Homepage" }, { @@ -27,7 +27,7 @@ "name": "FvS-eMail" }, { - "url": "https://dw.steinbeis.schule", + "url": "https://info.steinbeis.schule", "name": "FvS-Hilfesystem" }, { @@ -35,15 +35,23 @@ "name": "FvS-Moodle" }, { - "url": "https://nc.steinbeis.schule", - "name": "FvS-Nextcloud" + "url": "https://cloud.steinbeis.schule", + "name": "FvS-Schulcloud" + }, + { + "url": "https://nct.steinbeis.schule", + "name": "FvS-Nextcloud-Teacher (Nur für Lehrer)" + }, + { + "url": "https://git.steinbeis.schule", + "name": "FvS-Git Versionsverwaltung" }, { "url": "https://server.pn.steinbeis.schule", "name": "Schulkonsole" }, { - "url": "https://peleus.webuntis.com/WebUntis/?school=Ferd.von+Steinbeis#/basic/login", + "url": "https://steinbeis.webuntis.com/WebUntis/?school=steinbeis#/basic/login", "name": "FvS-Stundenplan" }, { diff --git a/roles/custom/fvs/tasks/main.yml b/roles/custom/fvs/tasks/main.yml index 738b4fe..2248651 100644 --- a/roles/custom/fvs/tasks/main.yml +++ b/roles/custom/fvs/tasks/main.yml @@ -29,7 +29,6 @@ - elpa-magit - emacs - filezilla - - freeplane - git - git-cola - gitg @@ -46,6 +45,7 @@ - libasound2-dev - libdbus-glib-1-2 ## needed for zotero - libnotify-bin ## needed for pwroff script + - libsqlite3-dev - libwayland-dev - libxcursor-dev - libxi-dev @@ -62,10 +62,13 @@ - okular-extra-backends ## needed for CHM files - pdf-presenter-console - php-cli + - php-sqlite3 - pipx - planner - pulseview + - python3-legacy-cgi - python3-paho-mqtt + - python3-pgzero - python3-websockets - qpdfview - shellcheck @@ -82,7 +85,7 @@ - unison-gtk - w3m - wireshark - - zulucrypt-gui + # - zulucrypt-gui ## no longer in trixie autoremove: true state: latest environment: @@ -155,6 +158,11 @@ dest: /etc/profile.d/ mode: '0644' +- name: Copy codeblocks config scripts + ansible.builtin.copy: + src: lmn-codeblocks.sh + dest: /etc/profile.d/ + mode: '0644' - name: Copy fvs-config.js to configure plasma ansible.builtin.copy: @@ -162,6 +170,16 @@ dest: /usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/fvs-config.js mode: '0644' +- name: Configure default KDE applications + ansible.builtin.blockinfile: + path: /etc/xdg/mimeapps.list + create: true + mode: '0644' + block: | + [Default Applications] + x-scheme-handler/http=firefox-esr.desktop; + x-scheme-handler/https=firefox-esr.desktop; + x-scheme-handler/mailto=thunderbird.desktop; - name: Configure some KDE aspects ansible.builtin.blockinfile: @@ -170,13 +188,22 @@ mode: '0644' block: | [KDE] - SingleClick=false + #SingleClick=false [KDE Action Restrictions][$i] action/start_new_session=false - #action/switch_user=false + action/switch_user=false #action/lock_screen=false +- name: Configure NumLock ON + ansible.builtin.blockinfile: + path: /etc/xdg/kcminputrc + create: true + mode: '0644' + block: | + [Keyboard] + NumLock=0 + - name: Start with empty session by default ansible.builtin.copy: dest: /etc/xdg/ksmserverrc @@ -220,7 +247,7 @@ ansible.builtin.blockinfile: path: /usr/share/sddm/themes/debian-breeze/Main.qml marker: // {mark} ANSIBLE MANAGED BLOCK - insertbefore: '\s+//Footer' + insertbefore: '^}$' block: | Text { id: hostname @@ -249,5 +276,12 @@ KERNEL=="mmcblk[0-9]", ENV{ID_NAME}=="?*", ENV{ID_SERIAL}=="?*", GROUP="domain users" KERNEL=="mmcblk[0-9]p[0-9]*", ENV{ID_NAME}=="?*", ENV{ID_SERIAL}=="?*", GROUP="domain users" +- name: Set KiCad 3Dmodel path + ansible.builtin.lineinfile: + path: /etc/environment.d/90lmn-kicad.conf + create: true + mode: '0644' + line: KICAD9_3DMODEL_DIR=/lmn/tools/KiCad/kicad-packages3D + - name: Include sync ansible.builtin.include_tasks: sync.yml diff --git a/roles/lmn_encrypt/defaults/main.yml b/roles/lmn_encrypt/defaults/main.yml new file mode 100644 index 0000000..b9b7837 --- /dev/null +++ b/roles/lmn_encrypt/defaults/main.yml @@ -0,0 +1,3 @@ +--- +encrypt_passphrase_initial: Muster! +encrypt_tpm2: false diff --git a/roles/lmn_encrypt/handlers/main.yml b/roles/lmn_encrypt/handlers/main.yml new file mode 100644 index 0000000..0ef929f --- /dev/null +++ b/roles/lmn_encrypt/handlers/main.yml @@ -0,0 +1,5 @@ +- name: Run update-grub + ansible.builtin.command: update-grub + +- name: Run update-dracut + ansible.builtin.command: dracut -f diff --git a/roles/lmn_encrypt/tasks/main.yml b/roles/lmn_encrypt/tasks/main.yml new file mode 100644 index 0000000..6c81e7b --- /dev/null +++ b/roles/lmn_encrypt/tasks/main.yml @@ -0,0 +1,46 @@ +--- +- name: Find device with LUKS holder + vars: + partitions: "{{ item.value.partitions | dict2items | selectattr('value.holders', 'search', 'luks|crypt') }}" + ansible.builtin.set_fact: + encrypt_device: "/dev/disk/by-id/{{ partitions[0].value.links.ids[0] }}" + when: + - item.value.partitions is defined + - item.value.partitions | dict2items | length > 0 + - item.value.partitions | dict2items | selectattr('value.holders', 'search', 'luks|crypt') | length > 0 + loop: "{{ ansible_devices | dict2items }}" + +- name: Get luks slots + ansible.builtin.command: + cmd: "systemd-cryptenroll {{ encrypt_device }}" + register: encrypt_slots_result + changed_when: false + when: encrypt_device is defined + +- name: Change Password of Luks password slot + ansible.builtin.command: + cmd: > + systemd-run -P --wait + -p SetCredential=cryptenroll.passphrase:{{ encrypt_passphrase_initial }} + -p SetCredential=cryptenroll.new-passphrase:{{ encrypt_passphrase }} + systemd-cryptenroll --password {{ encrypt_device }} --wipe-slot=password + no_log: true + when: + - encrypt_device is defined + - encrypt_passphrase is defined + - encrypt_slots_result.stdout_lines | length == 2 + - encrypt_slots_result.stdout_lines[1].startswith(' 0') + +- name: TPM Device Check + ansible.builtin.stat: + path: /dev/tpm0 + register: tpm_device + when: encrypt_device is defined + +- name: Include TPM2 role + ansible.builtin.include_tasks: + file: tpm2.yml + when: + - encrypt_device is defined + - encrypt_tpm2 + - tpm_device.stat.exists diff --git a/roles/lmn_encrypt/tasks/tpm2.yml b/roles/lmn_encrypt/tasks/tpm2.yml new file mode 100644 index 0000000..432ce2f --- /dev/null +++ b/roles/lmn_encrypt/tasks/tpm2.yml @@ -0,0 +1,42 @@ +--- +- name: Install tpm2-tools and dracut + ansible.builtin.apt: + name: + - tpm2-tools + - dracut + +- name: Enable tpm2-tss crypt module on dracut + ansible.builtin.copy: + dest: /etc/dracut.conf.d/crypt.conf + content: add_dracutmodules+=" tpm2-tss crypt " + mode: '0644' + notify: Run update-dracut + +- name: Comment out root device in crypttab + ansible.builtin.lineinfile: + dest: /etc/crypttab + regexp: '^([^#].*)' + line: '#\1' + backrefs: true + +- name: Insert luks support to GRUB_CMDLINE_LINUX + ansible.builtin.lineinfile: + dest: /etc/default/grub + regexp: '^(GRUB_CMDLINE_LINUX=).*' + line: '\1"rd.auto rd.luks=1"' + backrefs: true + notify: Run update-grub + +- name: Insert TPM2 to Luks slot + ansible.builtin.command: + cmd: > + systemd-run -P --wait + -p SetCredential=cryptenroll.passphrase:{{ encrypt_passphrase | default(encrypt_passphrase_initial) }} + systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs="" {{ encrypt_device }} --wipe-slot=tpm2 + no_log: true + when: "'tpm2' not in encrypt_slots_result.stdout" + +# - name: Update TPM2 Luks slot +# ansible.builtin.command: +# cmd: systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7+8 --unlock-tpm2-device=auto {{ encrypt_device }} --wipe-slot=tpm2 +# when: not grub_config.changed diff --git a/roles/lmn_exam/defaults/main.yml b/roles/lmn_exam/defaults/main.yml index da8c198..fc97945 100644 --- a/roles/lmn_exam/defaults/main.yml +++ b/roles/lmn_exam/defaults/main.yml @@ -1,2 +1,3 @@ --- exam_mode: true +exam_teacherpc_last_digit: 80 diff --git a/roles/lmn_exam/files/pam-exec.sh b/roles/lmn_exam/files/pam-exec.sh index 4f54861..f905cfc 100644 --- a/roles/lmn_exam/files/pam-exec.sh +++ b/roles/lmn_exam/files/pam-exec.sh @@ -5,10 +5,16 @@ if [[ "${PAM_USER}" =~ -exam$ ]]; then systemctl start firewalld.service + if [[ -f /usr/local/sbin/no-way-out-nftable ]]; then + /usr/local/sbin/no-way-out-nftable || true + fi if systemctl is-enabled --quiet libvirtd.service; then systemctl restart libvirtd.service fi elif ! (users | grep -q -- "-exam"); then + if /usr/sbin/nft list tables | /usr/bin/grep -q filtermacvtap; then + /usr/sbin/nft delete table netdev filtermacvtap || true + fi systemctl stop firewalld.service if systemctl is-enabled --quiet libvirtd.service; then systemctl restart libvirtd.service diff --git a/roles/lmn_exam/tasks/main.yml b/roles/lmn_exam/tasks/main.yml index 0e3bc4e..1d0893e 100644 --- a/roles/lmn_exam/tasks/main.yml +++ b/roles/lmn_exam/tasks/main.yml @@ -50,6 +50,38 @@ - pam-exec.sh - rmexam +- name: Append teacherPC to exam_destination_allowed_ipv4 addresses + ansible.builtin.set_fact: + exam_destination_allowed_ipv4: "{{ exam_destination_allowed_ipv4 + (exam_teacherpc_ips | default([ ansible_default_ipv4.address.rsplit('.', 1)[0] ~ '.' ~ exam_teacherpc_last_digit ])) }}" + when: + - exam_destination_allowed_ipv4 is defined + - exam_destination_allowed_ipv4 | length > 0 + - exam_teacherpc_ips is defined or exam_teacherpc_last_digit | default('') | string | length > 0 + +- name: Install no-way-out-policy + ansible.builtin.template: + src: no-way-out.xml.j2 + dest: "/etc/firewalld/policies/no-way-out-{{ item }}.xml" + mode: '0644' + vars: + zones: + - HOST + - "{{ 'libvirt' if vm_support | default(false) else '' }}" + loop: "{{ zones | reject('match','^$') }}" + when: + - exam_destination_allowed_ipv4 is defined + - exam_destination_allowed_ipv4 | length > 0 + +- name: Install no-way-out nf-table for macvtap device + ansible.builtin.template: + src: no-way-out-nftable.j2 + dest: "/usr/local/sbin/no-way-out-nftable" + mode: '0755' + when: + - exam_destination_allowed_ipv4 is defined + - exam_destination_allowed_ipv4 | length > 0 + - vm_support is defined and vm_support + - name: Enable login script via pam_exec.so ansible.builtin.lineinfile: dest: /etc/pam.d/common-session diff --git a/roles/lmn_exam/templates/no-way-out-nftable.j2 b/roles/lmn_exam/templates/no-way-out-nftable.j2 new file mode 100644 index 0000000..93305a9 --- /dev/null +++ b/roles/lmn_exam/templates/no-way-out-nftable.j2 @@ -0,0 +1,43 @@ +#!/usr/bin/bash + +set -eu + +interfaces=$(/usr/bin/ip link | /usr/bin/sed -En 's/.*(macvtap-.*)@.*/\1/p') +gateway=$(/usr/bin/ip route list default | /usr/bin/head -1 | /usr/bin/cut -f 3 -d " ") + +filterchain="" +for interface in ${interfaces}; do + filterchain=$(cat <<- EOF +${filterchain} + + chain filterin_${interface} { + type filter hook ingress device ${interface} priority filter; policy drop; + ip saddr \$allowed_ipv4 accept + ip saddr ${gateway} accept + ip saddr 255.255.255.255 accept + ether type arp accept + } + + chain filterout_${interface} { + type filter hook egress device ${interface} priority filter; policy drop; + ip daddr \$allowed_ipv4 accept + ip daddr ${gateway} accept + ip daddr 255.255.255.255 accept + ether type arp accept + } +EOF +) +done + + + +nft_table=$(cat <<- EOF +define allowed_ipv4 = { {{ exam_destination_allowed_ipv4 | join(",") }} } + +table netdev filtermacvtap { +${filterchain} +} +EOF +) + +echo "$nft_table" | /usr/sbin/nft -f - diff --git a/roles/lmn_exam/templates/no-way-out.xml.j2 b/roles/lmn_exam/templates/no-way-out.xml.j2 new file mode 100644 index 0000000..7cf782f --- /dev/null +++ b/roles/lmn_exam/templates/no-way-out.xml.j2 @@ -0,0 +1,10 @@ + +{% for address in exam_destination_allowed_ipv4 %} + + + + +{% endfor %} + + + diff --git a/roles/lmn_finish/handlers/main.yml b/roles/lmn_finish/handlers/main.yml new file mode 100644 index 0000000..bae24ff --- /dev/null +++ b/roles/lmn_finish/handlers/main.yml @@ -0,0 +1,4 @@ +--- +- name: Reboot client + ansible.builtin.command: + cmd: "shutdown -r -t 60" diff --git a/roles/lmn_finish/tasks/main.yaml b/roles/lmn_finish/tasks/main.yaml index 5f3a787..d7ec865 100644 --- a/roles/lmn_finish/tasks/main.yaml +++ b/roles/lmn_finish/tasks/main.yaml @@ -6,6 +6,8 @@ - "{{ extra_pkgs }}" - "{{ extra_pkgs1 }}" - "{{ extra_pkgs2 }}" + tags: + - baseinstall - name: Add backports for {{ ansible_distribution_release }} ansible.builtin.apt_repository: @@ -14,7 +16,7 @@ main non-free-firmware state: present update_cache: true -# when: extra_pkgs_bpo|length + when: extra_pkgs_bpo | length > 0 or extra_pkgs_bpo1 | length > 0 or extra_pkgs_bpo2 | length > 0 - name: Install extra packages from backports ansible.builtin.apt: @@ -25,6 +27,19 @@ - "{{ extra_pkgs_bpo }}" - "{{ extra_pkgs_bpo1 }}" - "{{ extra_pkgs_bpo2 }}" + when: extra_pkgs_bpo | length > 0 or extra_pkgs_bpo1 | length > 0 or extra_pkgs_bpo2 | length > 0 + + +- name: Check if former ansible-stamp exists + ansible.builtin.stat: + path: /var/local/ansible-stamps + register: stamp_exists + +- name: Trigger Reboot if no former ansible-run is found + ansible.builtin.debug: + msg: "First Ansible-Run on Client - Reboot handler started" + changed_when: not stamp_exists.stat.exists + notify: "Reboot client" - name: Timestamp successfull run and send up-to-date report ansible.builtin.shell: diff --git a/roles/lmn_kde/defaults/main.yml b/roles/lmn_kde/defaults/main.yml index 779142b..065c5ba 100644 --- a/roles/lmn_kde/defaults/main.yml +++ b/roles/lmn_kde/defaults/main.yml @@ -3,9 +3,10 @@ kde_desktop_pkg: - akonadi-backend-sqlite - arduino - bluefish - - calligra + # - calligra - codeblocks - dia + - filius - flameshot - freecad - fritzing @@ -14,8 +15,9 @@ kde_desktop_pkg: - inkscape - kde-full - keepassxc + - kicad + - kicad-doc-de - librecad - - mu-editor - openboard - qtcreator - spyder @@ -34,3 +36,5 @@ kde_desktop_pkg: - xdg-desktop-portal-kde - xdg-desktop-portal-wlr # share screen in browser - xournalpp + +kde_desktop_pkg_bpo: [ ] diff --git a/roles/lmn_kde/tasks/main.yml b/roles/lmn_kde/tasks/main.yml index 052606b..0b76358 100644 --- a/roles/lmn_kde/tasks/main.yml +++ b/roles/lmn_kde/tasks/main.yml @@ -8,19 +8,14 @@ repo: deb http://deb.debian.org/debian/ {{ ansible_distribution_release }}-backports main non-free-firmware state: present update_cache: true + when: kde_desktop_pkg_bpo | length > 0 - name: Install extra packages from backports ansible.builtin.apt: - name: - - filius - - kicad - - kicad-doc-de - - libreoffice - - libreoffice-l10n-de - - libreoffice-qt5 - state: latest # noqa package-latest + name: "{{ kde_desktop_pkg_bpo }}" autoremove: true default_release: "{{ ansible_distribution_release }}-backports" + when: kde_desktop_pkg_bpo | length > 0 - name: Create akonadi config dir diff --git a/roles/lmn_localhome/tasks/main.yml b/roles/lmn_localhome/tasks/main.yml index 3122720..a06998b 100644 --- a/roles/lmn_localhome/tasks/main.yml +++ b/roles/lmn_localhome/tasks/main.yml @@ -9,7 +9,7 @@ ansible.builtin.blockinfile: path: /usr/share/sddm/themes/debian-breeze/Main.qml marker: // {mark} ANSIBLE MANAGED BLOCK localhome - insertbefore: '\s+//Footer' + insertbefore: '^}$' block: | Text { id: localhome @@ -33,7 +33,6 @@ dest: /etc/profile.d/lmn-logout.sh mode: '0755' content: | - [[ "${UID}" -gt 10000 ]] && ! findmnt "/lmn/media/${USER}/home" > /dev/null && exit 0 {% if localhome_logout_missing_serverhome %} [[ "${UID}" -gt 10000 ]] && ! findmnt /srv/samba/schools/default-school > /dev/null && exit 0 {% endif %} diff --git a/roles/lmn_misc/files/bootorder.sh b/roles/lmn_misc/files/bootorder.sh index a0fb6cd..e3ef2a9 100644 --- a/roles/lmn_misc/files/bootorder.sh +++ b/roles/lmn_misc/files/bootorder.sh @@ -5,11 +5,11 @@ set -eu cur="$(efibootmgr | grep -Ei 'BootOrder:' | \ - sed -E 's/^BootOrder: ([[:xdigit:]]{4}),.+$/\1/')" -pxeip4="$(efibootmgr | grep -Ei "IP.*4" | \ - sed -E 's/^Boot([[:xdigit:]]{4}).+$/\1/')" + sed -E 's/^BootOrder: ([[:xdigit:]]{4}),.+$/\1/')" +pxeip4="$(efibootmgr | grep -Ei "IP.{0,5}4" | \ + sed -E 's/^Boot([[:xdigit:]]{4}).+$/\1/' | paste -sd, -)" debian="$(efibootmgr | grep -Ei "debian" | \ - sed -E 's/^Boot([[:xdigit:]]{4}).+$/\1/')" + sed -E 's/^Boot([[:xdigit:]]{4}).+$/\1/' | paste -sd, -)" if [[ "$cur" != "$pxeip4" ]] && [[ -n "$pxeip4" ]] && [[ -n "$debian" ]] ; then efibootmgr -o $pxeip4,$debian diff --git a/roles/lmn_misc/tasks/main.yml b/roles/lmn_misc/tasks/main.yml index 22134c5..23dce2b 100644 --- a/roles/lmn_misc/tasks/main.yml +++ b/roles/lmn_misc/tasks/main.yml @@ -98,7 +98,7 @@ export superusers password_pbkdf2 root {{ grub_pwd }} notify: Run update-grub - when: grub_pwd|default(false) + when: grub_pwd | bool | default(false) - name: Allow booting grub menu entries ansible.builtin.lineinfile: @@ -167,6 +167,8 @@ src: reporter.j2 dest: /usr/local/sbin/reporter mode: '0755' + tags: + - baseinstall - name: Provide services and timers for reporter ansible.builtin.copy: @@ -177,12 +179,16 @@ - reporter.service - reporter.timer when: misc_reporter + tags: + - baseinstall - name: Enable reporter.timer ansible.builtin.systemd: name: reporter.timer enabled: true when: misc_reporter + tags: + - baseinstall # Prepare CloneScreen on Presenter PCs diff --git a/roles/lmn_network/tasks/main.yml b/roles/lmn_network/tasks/main.yml index 7a39349..571c107 100644 --- a/roles/lmn_network/tasks/main.yml +++ b/roles/lmn_network/tasks/main.yml @@ -5,14 +5,14 @@ mode: '0644' content: > {{ apt_conf }} - when: apt_conf|default(false) + when: apt_conf | bool | default(false) - name: Set NTP server ansible.builtin.lineinfile: path: /etc/systemd/timesyncd.conf insertafter: '^#NTP=' line: NTP={{ ntp_serv }} - when: ntp_serv|default(false) + when: ntp_serv | bool | default(false) - name: Add proposed-updates repository ansible.builtin.apt_repository: diff --git a/roles/lmn_printer/tasks/main.yml b/roles/lmn_printer/tasks/main.yml index 960b1fa..996cb2e 100644 --- a/roles/lmn_printer/tasks/main.yml +++ b/roles/lmn_printer/tasks/main.yml @@ -37,7 +37,7 @@ line: "SystemGroup root lpadmin {{ printer_admin_group }}" regexp: '^SystemGroup' state: present - when: printer_admin_group | length + when: printer_admin_group | length > 0 - name: Disable cups-browsed ansible.builtin.systemd: diff --git a/roles/lmn_security/tasks/main.yml b/roles/lmn_security/tasks/main.yml index 62e2754..6c9edcf 100644 --- a/roles/lmn_security/tasks/main.yml +++ b/roles/lmn_security/tasks/main.yml @@ -5,6 +5,8 @@ key: "{{ item }}" loop: "{{ keys2deploy }}" when: keys2deploy is defined + tags: + - baseinstall - name: Allow sudo without password for ansible ansible.builtin.lineinfile: @@ -14,12 +16,16 @@ owner: root group: root mode: '0700' + tags: + - baseinstall - name: Disable ansible user login ansible.builtin.user: name: ansible password_lock: true when: security_defaultuser_login_disable + tags: + - baseinstall - name: Limit SSH access to user ansible ansible.builtin.blockinfile: diff --git a/roles/lmn_sssd/defaults/main.yml b/roles/lmn_sssd/defaults/main.yml new file mode 100644 index 0000000..e7664ac --- /dev/null +++ b/roles/lmn_sssd/defaults/main.yml @@ -0,0 +1,2 @@ +--- +sssd_domjoin_user: global-admin diff --git a/roles/lmn_sssd/handlers/main.yml b/roles/lmn_sssd/handlers/main.yml index 6fdda36..cddc361 100644 --- a/roles/lmn_sssd/handlers/main.yml +++ b/roles/lmn_sssd/handlers/main.yml @@ -1,6 +1,5 @@ - name: Restart sssd - ansible.builtin.service: + ansible.builtin.systemd: name: sssd state: restarted enabled: true - listen: "Restart sssd" diff --git a/roles/lmn_sssd/tasks/main.yml b/roles/lmn_sssd/tasks/main.yml index ed44ce5..c816d13 100644 --- a/roles/lmn_sssd/tasks/main.yml +++ b/roles/lmn_sssd/tasks/main.yml @@ -10,15 +10,27 @@ ansible.builtin.template: src: sssd.conf.j2 dest: /etc/sssd/sssd.conf - mode: '0600' + mode: '0640' notify: Restart sssd - ## Either one of the variables is defined: +- name: Check if the machine account password and the join are still valid + ansible.builtin.shell: + cmd: adcli testjoin -D {{ domain | upper }} + register: adcli_test_result + failed_when: false + changed_when: false + + # If domjoin not valid: - name: Join the domain ansible.builtin.shell: cmd: > - echo "{{ ansible_cmdline.adpw | default('') + adpw.user_input | default('') }}" | - adcli join --stdin-password -U global-admin {{ domain | upper }} - when: > - ansible_cmdline.adpw | default('') | length > 0 or - adpw.user_input | default('') | length > 0 + echo "{{ ad_passwd }}" | adcli join --stdin-password -U {{ ad_user }} {{ domain | upper }} + no_log: true + vars: + ad_user: "{{ 'global-admin' if (adpw.user_input | default(ansible_cmdline.adpw) | default('') | length > 0) else sssd_domjoin_user }}" + ad_passwd: "{{ adpw.user_input | default('') if adpw.user_input | default ('') | length > 0 else ansible_cmdline.adpw | default(sssd_domjoin_passwd) | default('') }}" + throttle: 1 + when: + - adpw.user_input | default('') | length > 0 or + ansible_cmdline.adpw | default(sssd_domjoin_passwd) | default('') | length > 0 + - adcli_test_result.rc != 0 diff --git a/roles/lmn_sssd/templates/sssd.conf.j2 b/roles/lmn_sssd/templates/sssd.conf.j2 index fc3bf48..1591f1d 100644 --- a/roles/lmn_sssd/templates/sssd.conf.j2 +++ b/roles/lmn_sssd/templates/sssd.conf.j2 @@ -9,7 +9,9 @@ ad_domain = {{ domain }} id_provider = ad access_provider = ad use_fully_qualified_names = False +{% if localhome is defined and localhome %} cache_credentials = True +{% endif %} krb5_store_password_if_offline = True default_shell = /usr/bin/bash # default: # ldap_id_mapping = True @@ -17,6 +19,7 @@ ad_gpo_access_control = disabled ad_gpo_ignore_unreadable = True ad_maximum_machine_account_password_age = 0 ignore_group_members = True +krb5_renew_interval = 1h {% if localhome is defined and localhome %} override_homedir = /home/%u {% endif %} diff --git a/roles/lmn_tmpfixes/tasks/main.yml b/roles/lmn_tmpfixes/tasks/main.yml index 8e90138..23e0bf8 100644 --- a/roles/lmn_tmpfixes/tasks/main.yml +++ b/roles/lmn_tmpfixes/tasks/main.yml @@ -8,3 +8,27 @@ - bookworm.yml - cleanup.yml when: ansible_distribution_release == "bookworm" + +- name: Set chromium gl-flags fixing AMD graphic issues + ansible.builtin.copy: + dest: /etc/chromium.d/fvs + content: | + export CHROMIUM_FLAGS="$CHROMIUM_FLAGS --use-gl=desktop" + when: ansible_board_vendor == "LENOVO" and + (ansible_board_name == "312D" or ansible_board_name == "312A") + +- name: Fix 8086:4909 external graphics card + ansible.builtin.replace: + dest: "/etc/default/grub" + regexp: 'GRUB_CMDLINE_LINUX=""$' + replace: 'GRUB_CMDLINE_LINUX="i915.force_probe=4909"' + notify: Run update-grub + when: ansible_board_vendor == "LENOVO" and ansible_board_name == "32CB" + +- name: Remove calligra + ansible.builtin.apt: + name: + - calligra + state: absent + purge: true + autoremove: true diff --git a/roles/lmn_vm/files/lmn-vm b/roles/lmn_vm/files/lmn-vm index 7d4011e..006b84c 100644 --- a/roles/lmn_vm/files/lmn-vm +++ b/roles/lmn_vm/files/lmn-vm @@ -3,6 +3,11 @@ %role-student ALL=(lmnsynci) NOPASSWD: /usr/local/bin/vm-sync %examusers ALL=(lmnsynci) NOPASSWD: /usr/local/bin/vm-sync +# vm-delete: Delete VM-Images +%role-teacher ALL=(lmnsynci) NOPASSWD: /usr/local/bin/vm-delete +%role-student ALL=(lmnsynci) NOPASSWD: /usr/local/bin/vm-delete +%examusers ALL=(lmnsynci) NOPASSWD: /usr/local/bin/vm-delete + # vm-aria2: Start/Stop aria2 as systemd-service for VM-Images lmnsynci ALL=(root) NOPASSWD: /usr/local/bin/vm-aria2 diff --git a/roles/lmn_vm/files/vm-delete b/roles/lmn_vm/files/vm-delete new file mode 100755 index 0000000..84a8aba --- /dev/null +++ b/roles/lmn_vm/files/vm-delete @@ -0,0 +1,45 @@ +#!/bin/bash + +set -eu + +directory="/lmn/vm" + +if [ ! -d "$directory" ]; then + echo "No VM directory found." + exit 1 +fi + +qcow2_files=("$directory"/*.qcow2) + +if [ "${#qcow2_files[@]}" -eq 0 ]; then + echo "Keine QCOW2-Dateien gefunden." + exit 0 +fi + +echo "Gefundene QCOW2-Dateien:" +echo "-------------------------------------------------------------" +printf "%-50s %10s\n" "Datei" "Größe (MB)" +echo "-------------------------------------------------------------" + +for file in "${qcow2_files[@]}"; do + size=$(du -m "$file" | cut -f1) # Größe in MB + printf "%-50s %10d\n" "$file" "$size" +done + +echo "-------------------------------------------------------------" + +for file in "${qcow2_files[@]}"; do + read -rp "Möchtest du die Datei $file löschen? (j/n) " confirmation + if [[ "$confirmation" == "j" || "$confirmation" == "J" ]]; then + link_count=$(stat -c %h "$file") + rm "$file" + echo "$file wurde gelöscht." + if [ "$link_count" -gt 1 ]; then + echo "Achtung: $file hat noch $((link_count - 1)) weitere Hardlinks." + echo "Diese liegen evtl. unter:" + echo "- /var/tmp/${UID}/vm/ (temporäre VMs, werden automatisch beim Neustart gelöscht)" + echo "- /var/vm/${UID}/ (persistente VMs)" + fi + echo + fi +done diff --git a/roles/lmn_vm/files/vm-link-images b/roles/lmn_vm/files/vm-link-images index e4c8618..0eccd04 100755 --- a/roles/lmn_vm/files/vm-link-images +++ b/roles/lmn_vm/files/vm-link-images @@ -19,8 +19,9 @@ done shift "$((OPTIND -1))" # link system-VM-Images to User VM Directory -for i in *.qcow2; do - [[ -f "${VM_DIR}/${i}" ]] || ln "${i}" "${VM_DIR}/${i}" +for filename in "$@"; do + filename="$(basename ${filename})" + [[ -f "${VM_DIR}/${filename}" ]] || ln "${filename}" "${VM_DIR}/${filename}" done # allow lmnsynci to remove old vm images diff --git a/roles/lmn_vm/files/vm-netboot b/roles/lmn_vm/files/vm-netboot index c21024f..92ca621 100755 --- a/roles/lmn_vm/files/vm-netboot +++ b/roles/lmn_vm/files/vm-netboot @@ -7,10 +7,10 @@ set -eu ## Imporant for all virsh libvirt calls: export XDG_CONFIG_HOME="/var/tmp/vm/${UID}" -menu=(standard "CLI Standard Debian GNU/Linux NFS" - standard-ram "CLI Standard Debian GNU/Linux RAM" - kde-desktop "KDE Plasma Desktop Debian GNU/Linux NFS" - gnome-desktop "Gnome Desktop Debian GNU/Linux NFS") +menu=(standard-edu "CLI Standard Debian GNU/Linux NFS" + standard-edu-ram "CLI Standard Debian GNU/Linux RAM" + kde-edu "KDE Plasma Desktop Debian GNU/Linux NFS" + gnome-edu "Gnome Desktop Debian GNU/Linux NFS") img=$(dialog --clear --backtitle "Virtual Machine Chooser" \ --title "Choose the Virtual Machine to Start" \ --menu "Start VM:" 12 70 6 "${menu[@]}" 2>&1 >/dev/tty) @@ -22,6 +22,8 @@ mac="$(ip link | grep -A1 -m1 "macvtap-" | \ sed -nE "s%\s+link/ether ([[:xdigit:]:]{17}) .+%\1%p")" tapdev="$(ip link | grep -A1 -m1 "macvtap-" | sed -nE "s%^[1-9]:\s(\S+)@.*%\1%p")" +livebox=$(host livebox | sed -E "s/.+ ([0-9.]+)$/\1/") + if [[ $# -eq 0 ]] ; then mem=$(sed -En "s/^MemAvailable:\s+([0-9]+)\s+kB/\1/p" /proc/meminfo) cpu=$(sed -En "0,/^cpu cores/s/^cpu cores\s+:\s+([0-9]+)/\1/p" /proc/cpuinfo) @@ -31,8 +33,8 @@ else arg=("$@") fi -kernel="http://livebox/d-i/n-live/${img%-ram}/live/vmlinuz" -initrd="http://livebox/d-i/n-live/${img%-ram}/live/initrd.img" +kernel="http://${livebox}/d-i/n-live/${img%-ram}/live/vmlinuz" +initrd="http://${livebox}/d-i/n-live/${img%-ram}/live/initrd.img" kargs=(boot=live components splash locales=de_DE.UTF-8 keyboard-layouts=de swap=true live-config.timezone=Europe/Berlin) @@ -42,10 +44,10 @@ case "$img" in kargs+=(console=ttyS0) ;;& *-ram) - kargs+=("fetch=http://10.190.1.2/d-i/n-live/${img%-ram}/live/filesystem.squashfs") + kargs+=("root=live:nfs4:${livebox}:/images/${img%-ram}/live/filesystem.squashfs rd.live.ram=1") ;; *) - kargs+=(netboot=nfs "nfsroot=10.190.1.2:/srv/nfs/debian-live/${img%-ram}") + kargs+=("root=live:nfs4:${livebox}:/images/${img%-ram}/live/filesystem.squashfs") ;; esac diff --git a/roles/lmn_vm/files/vm-run b/roles/lmn_vm/files/vm-run index a957a49..af0bd67 100755 --- a/roles/lmn_vm/files/vm-run +++ b/roles/lmn_vm/files/vm-run @@ -90,17 +90,21 @@ create_clone() { local VM_NAME="$1" if ! [[ -f "${VM_SYSDIR}/${VM_NAME}.qcow2" || -f "${VM_DIR}/${VM_NAME}.qcow2" ]]; then - echo "qcow2 File does not exists." >&2 - exit 1 + echo "qcow2 File does not exists." >&2 + exit 1 fi # Create User-VM-Dir and link system VM-Images [[ -d "${VM_DIR}" ]] || mkdir -p "${VM_DIR}" - if [[ "${PERSISTENT}" -eq 1 ]]; then - sudo /usr/local/bin/vm-link-images -p - else - sudo /usr/local/bin/vm-link-images - fi + IMAGE="${VM_NAME}.qcow2" + while [[ -n ${IMAGE} ]]; do + if [[ "${PERSISTENT}" -eq 1 ]]; then + sudo /usr/local/bin/vm-link-images -p "${IMAGE}" + else + sudo /usr/local/bin/vm-link-images "${IMAGE}" + fi + IMAGE="$(qemu-img info -U "${VM_DIR}/${IMAGE}" | grep "^backing file:" | cut -d ' ' -f 3)" + done # Create backing file cd "${VM_DIR}" @@ -130,18 +134,30 @@ create_printerlist() { } create_mountlist() { - if id | grep -q teachers; then - NETHOME=/srv/samba/schools/default-school/teachers/$USER - else - NETHOME=(/srv/samba/schools/default-school/students/*/"$USER") - fi - NETHOME="${NETHOME#/srv/samba/schools}" - cat << EOF > "/lmn/media/${USER}/.mounts.csv" + NETHOMEPART="${NETHOME#/srv/samba/schools}" + cat << EOF > "${VMINFO_DIR}/.mounts.csv" Drive;Remotepath -H;\\\\10.190.1.1${NETHOME//\//\\} -T;\\\\10.190.1.1\default-school\share +H;\\\\server.pn.steinbeis.schule${NETHOMEPART//\//\\} +T;\\\\server.pn.steinbeis.schule\\default-school\\share EOF - echo "${USER}" > "/lmn/media/${USER}/.user" + echo "${USER}" > "/${VMINFO_DIR}/.user" +} + +start_virtiofs_service() { + local target_name=$1 + local shared_dir=$2 + local drive_letter=$3 + local socket="/run/user/${UID}/virtiofs-${VM_NAME}-${target_name,,}.sock" + + systemd-run --user /usr/local/bin/virtiofsd --uid-map=":${GUEST_UID}:${UID}:1:" --gid-map=":${GUEST_GID}:$(id -g):1:" \ + --socket-path "${socket}" --shared-dir "${shared_dir}" --syslog + + if [[ $? -ne 0 ]]; then + echo "Error starting virtiofsd for ${target_name}." >&2 + return 1 + fi + + LIBVIRTOPTS="${LIBVIRTOPTS} --filesystem driver.type=virtiofs,accessmode=passthrough,target.dir=${target_name},xpath1.set=./source/@socket=${socket}" } start_virtiofsd() { @@ -151,9 +167,17 @@ start_virtiofsd() { [[ "$GUEST_GID" == 0 ]] && GUEST_GID=1010 fi # END temporary fix - socket="/run/user/$(id -u $USER)/virtiofs-${VM_NAME}.sock" - systemd-run --user /usr/local/bin/virtiofsd --uid-map=:${GUEST_UID}:${UID}:1: --gid-map=:${GUEST_GID}:$(id -g):1: \ - --socket-path "$socket" --shared-dir "/lmn/media/${USER}" --syslog + + # start_virtiofs_service "VM-Data" "/lmn/media/${USER}" "Y" + # start_virtiofs_service "default-school" "/srv/samba/schools/default-school" "Y" + + # Home@PC / VM-Data + # if the environment variable VMLEGACY is set, /lmn/media/USER is forced + if [[ "${HOME}" != "${NETHOME}" && ! -v VMLEGACY ]]; then + start_virtiofs_service "Home_Linux" "${HOME}" "Y" + else + start_virtiofs_service "VM-Data" "/lmn/media/${USER}" "Y" + fi } ask_really_persistent() { @@ -216,7 +240,7 @@ while true; do shift ;; -o | --options ) - LIBVIRTOPTS=$2 + LIBVIRTOPTS="${LIBVIRTOPTS} $2" shift 2 ;; --no-viewer ) @@ -267,6 +291,7 @@ while true; do type="ethernet,mac=${mac},target.dev=${interface},xpath1.set=./target/@managed=no,model.type=virtio" LIBVIRTOPTS="${LIBVIRTOPTS} --network type=$type" done + LIBVIRTOPTS="${LIBVIRTOPTS} --check mac_in_use=off" shift ;; --os ) @@ -315,18 +340,38 @@ if ! virsh --connect="${QEMU}" list | grep "${VM_NAME}-clone"; then check_images fi if [[ "${NEWCLONE}" = 1 ]] || [[ ! -f "${VM_DIR}/${VM_NAME}-clone.qcow2" ]]; then - create_clone "${VM_NAME}" + create_clone "${VM_NAME}" fi # delete the old vm virsh --connect=qemu:///session undefine --nvram "${VM_NAME}-clone" || echo "${VM_NAME}-clone did not exist" #trap exit_script SIGHUP SIGINT SIGTERM + for dir in teachers examusers staff parents; do + if [[ -d "/srv/samba/schools/default-school/${dir}/${USER}" ]]; then + NETHOME="/srv/samba/schools/default-school/${dir}/${USER}" + break + fi + done + if [[ -z "${NETHOME+x}" ]]; then + NETHOME=(/srv/samba/schools/default-school/students/*/"$USER") + fi + + if [[ "${HOME}" != "${NETHOME}" ]]; then + VMINFO_DIR="${HOME}" + else + VMINFO_DIR="/lmn/media/${USER}" + fi create_printerlist create_mountlist # start virtiofsd-service [[ "${QEMU}" = 'qemu:///session' ]] && start_virtiofsd + # Create VMInfo Json file + #( umask 027; ./vm-create-vminfo > "${VMINFO_DIR}/.vminfo.json" ) + # Start vminfo.timer + systemctl --user restart vminfo.timer + uuid=$(openssl rand -hex 16) uuid="${uuid:0:8}-${uuid:8:4}-${uuid:12:4}-${uuid:16:4}-${uuid:20:12}" @@ -348,7 +393,6 @@ if ! virsh --connect="${QEMU}" list | grep "${VM_NAME}-clone"; then --memorybacking source.type=memfd,access.mode=shared \ --disk "${VM_DIR}/${VM_NAME}-clone.qcow2",driver.discard=unmap,target.bus=scsi,cache=writeback \ --network=bridge=virbr0,model.type=virtio \ - --filesystem driver.type=virtiofs,accessmode=passthrough,target.dir=virtiofs,xpath1.set=./source/@socket="/run/user/${UID}/virtiofs-${VM_NAME}.sock" \ --controller type=scsi,model=virtio-scsi \ --check path_in_use=off \ --connect="${QEMU}" \ diff --git a/roles/lmn_vm/files/vm-vminfo b/roles/lmn_vm/files/vm-vminfo new file mode 100755 index 0000000..559d47f --- /dev/null +++ b/roles/lmn_vm/files/vm-vminfo @@ -0,0 +1,117 @@ +#!/usr/bin/python3 + +import argparse +import struct +import subprocess +import json +import sys + +from os import environ,path +from impacket.krb5.ccache import CCache +from base64 import b64encode + +home = "" +nethome = "" +vminfo = {} + +def get_printers(): + printers = [] + try: + result = subprocess.run(['lpstat', '-v'], capture_output=True, text=True, check=True) + for line in result.stdout.splitlines(): + # Extrahiere den Druckernamen + printer_name = line.split()[2].rstrip(':') + ipp_url = f"ipp://192.168.122.1/printers/{printer_name}" + printer = { 'Name': printer_name, 'IppURL': ipp_url } + printers.append(printer) + return printers + except subprocess.CalledProcessError as e: + sys.stderr.write(f"Fehler beim Abrufen der Drucker: {e}") + return [] + +def get_groups(username): + try: + result = subprocess.run(['id', '-Gnz', username], capture_output=True, text=True, check=True) + groups = result.stdout.strip().split('\0') + return groups + except subprocess.CalledProcessError as e: + sys.stderr.write(f"Fehler beim Abrufen der Gruppen: {e}") + return [] + +def get_krb5 (): + krb5 = {} + ccachefilename = environ.get('KRB5CCNAME').replace('FILE:', '') + if ccachefilename: + try: + ccache = CCache.loadFile(ccachefilename) + cred = ccache.toKRBCRED() + cred_enc = b64encode(cred) + krb5['cred'] = cred_enc.decode('utf-8') + krb5['starttime'] = ccache.credentials[0]['time']['starttime'] + krb5['endtime'] = ccache.credentials[0]['time']['endtime'] + krb5['renew_till'] = ccache.credentials[0]['time']['renew_till'] + except: + sys.stderr.write("Fehler beim Ticket laden") + return krb5 + +def get_mounts(): + mounts = [] + mounts.append({ 'Drive': 'H', 'RemotePath': '\\\\server.pn.steinbeis.schule' + nethome.replace('/srv/samba/schools','').replace('/','\\'), 'Name': 'Home_Server' }) + mounts.append({ 'Drive': 'T', 'RemotePath': '\\\\server.pn.steinbeis.schule\default-school\share', 'Name': 'Tausch' }) + return mounts + +def get_user_folders(): + HOME="H:" + if environ.get('HOME') != nethome: + HOME="Y:" + folders = [] + folders.append( {'Name': 'Personal', 'Path': f"{HOME}\Dokumente"} ) + folders.append( {'Name': 'My Pictures', 'Path': f"{HOME}\Bilder"} ) + folders.append( {'Name': 'My Music', 'Path': f"{HOME}\Musik"} ) + folders.append( {'Name': 'My Video', 'Path': f"{HOME}\Videos"} ) + return folders + +def get_quickaccess(): + quickaccess = [] + quickaccess.append( 'H:\\transfer' ) + return quickaccess + +def parse_args(): + parser = argparse.ArgumentParser() + #parser.add_argument('input_file', help="File in kirbi (KRB-CRED) or ccache format") + #parser.add_argument('output_file', help="Output file") + return parser.parse_args() + + +def main(): + global home, nethome + + args = parse_args() + + home = environ.get('HOME') + + vminfo['User'] = environ.get('USER') + vminfo['Groups'] = get_groups(environ.get('USER')) + + for dir in ['teachers','examusers','staff','parents']: + potential_path = f"/srv/samba/schools/default-school/{dir}/{vminfo['User']}" + if path.isdir(potential_path): + nethome = potential_path + break + if not nethome: + result = subprocess.run(['find', '/srv/samba/schools/default-school/students/', '-name', vminfo['User'], '-maxdepth', '2', '-type', 'd'], capture_output=True, text=True, check=False) + nethome = result.stdout.splitlines()[0] + + vminfo['Printers'] = get_printers() + vminfo['krb5'] = get_krb5() + vminfo['Mounts'] = get_mounts() + vminfo['UserShellFolders'] = get_user_folders() + vminfo['QuickAccess'] = get_quickaccess() + + vminfo_json = json.dumps(vminfo, ensure_ascii=False, indent=4) + print(vminfo_json) + +if __name__ == '__main__': + main() + + diff --git a/roles/lmn_vm/tasks/main.yml b/roles/lmn_vm/tasks/main.yml index a39325a..e2c312b 100644 --- a/roles/lmn_vm/tasks/main.yml +++ b/roles/lmn_vm/tasks/main.yml @@ -18,7 +18,9 @@ - mktorrent - libvirt-daemon-system - virt-manager + - virt-viewer - dialog # for vm-netboot menu + - python3-impacket # - name: allow all users to use VMs # lineinfile: @@ -27,32 +29,6 @@ # insertafter: '#auth_unix_rw = "polkit"' # notify: reload libvirtd -- name: Configure pam_mount for VM bind mounts - ansible.builtin.blockinfile: - dest: /etc/security/pam_mount.conf.xml - marker: "" - block: | - - rootansibleDebian-gdmsddm{% if localuser %}{{ localuser }}{% endif %} - - rootansibleDebian-gdmsddm{% if localuser %}{{ localuser }}{% endif %} - - rootansibleDebian-gdmsddm{% if localuser %}{{ localuser }}{% endif %} - - insertafter: "" - - name: Use umount script for proper cleanup ansible.builtin.blockinfile: dest: /etc/security/pam_mount.conf.xml @@ -142,6 +118,7 @@ group: root mode: '0755' loop: + - vm-delete - vm-create - vm-rebase - vm-run @@ -149,6 +126,7 @@ - vm-sync - vm-link-images - vm-virtiofsd + - vm-vminfo - virtiofsd - vm-aria2 - uploadseed @@ -236,3 +214,26 @@ src: vm-netboot dest: /usr/local/bin/ mode: '0755' + +- name: Provide vminfo service + ansible.builtin.copy: + content: | + [Unit] + Description=Create .vminfo.json for VMs + [Service] + Type=simple + ExecStart=/usr/bin/bash -c 'umask 027; /usr/local/bin/vm-vminfo > "{% if localhome %}/home{% else %}/lmn/media{% endif %}/${USER}/.vminfo.json"' + dest: /etc/systemd/user/vminfo.service + mode: '0644' + +- name: Provide vminfo timer + ansible.builtin.copy: + content: | + [Unit] + Description=Timer for vm-info + [Timer] + OnActiveSec=0s + OnUnitActiveSec=1h + Persistent=true + dest: /etc/systemd/user/vminfo.timer + mode: '0644' diff --git a/roles/lmn_vpn/files/10-lmn-mount.sh b/roles/lmn_vpn/files/10-lmn-mount.sh index 6f42725..cabbc58 100755 --- a/roles/lmn_vpn/files/10-lmn-mount.sh +++ b/roles/lmn_vpn/files/10-lmn-mount.sh @@ -13,30 +13,32 @@ if [[ "$CONNECTION_ID" = "VPN-Schule" ]]; then # Exit if server is already mounted findmnt /srv/samba/schools/default-school > /dev/null && exit 0 - if ! klist -s -c "${KRB5CCNAME}"; then - #echo "try to renew KRB5-Ticket" >&2 - #sudo -u "${USERNAME}" kinit -R -c "${KRB5CCNAME}" - echo "KRB5-Ticket is expired. Sleep 3 seconds and hope it will be renewed after." >&2 - sleep 3 - fi + counter=1 + while ! klist -s -c "${KRB5CCNAME}"; do + (( counter > 30 )) && exit 0 + echo "KRB5-Ticket is expired. Sleep 1 seconds and hope it will be renewed after." >&2 + # if (( counter == 10 )); then + # echo "try to renew KRB5-Ticket" >&2 + # sudo -u "${USERNAME}" kinit -R -c "${KRB5CCNAME}" + # fi + sleep 1 + ((counter++)) + done echo "prepare mountpoints" >&2 umask 0002 mkdir -p /srv/samba/schools/default-school chmod 777 /srv/samba/schools/default-school - mkdir -p "/lmn/media/${USERNAME}/share" - + mount -t cifs //server/default-school/ /srv/samba/schools/default-school \ -o "sec=krb5i,cruid=${USERID},user=${USERNAME},uid=${USERID},gid=${GROUPID},file_mode=0700,dir_mode=0700,mfsymlinks,nobrl,actimeo=600,cache=loose,echo_interval=10" echo "after mount" >&2 - mount --bind /srv/samba/schools/default-school/share "/lmn/media/${USERNAME}/share" SUDO_USER=$USERNAME /usr/local/bin/install-printers.sh elif [[ "$NM_DISPATCHER_ACTION" = "pre-down" ]]; then # FIXME: Only umount server when Wireguard-Connection was the only connection to server. # Dirty fix (works only in fvs-IP-Range) if ! (ip r s | grep "10.190." | grep -v wg0); then - echo "Try to umount server shares" - umount "/lmn/media/${USERNAME}/share" + echo "Try to umount server" umount /srv/samba/schools/default-school fi fi diff --git a/roles/lmn_vpn/files/mountserver b/roles/lmn_vpn/files/mountserver index 71c61cc..708a26e 100644 --- a/roles/lmn_vpn/files/mountserver +++ b/roles/lmn_vpn/files/mountserver @@ -3,7 +3,6 @@ set -eu exit_script() { echo "unmounting media - terminated by trap!" >> "/tmp/${SUDO_UID}-exit-mount.log" - findmnt "/lmn/media/${SUDO_USER}/share" && umount "/lmn/media/${SUDO_USER}/share" findmnt "/srv/samba/schools/default-school" && umount "/srv/samba/schools/default-school" trap - SIGHUP SIGINT SIGTERM # clear the trap kill -- -$$ # Sends SIGTERM to child/sub processes @@ -14,11 +13,9 @@ findmnt /srv/samba/schools/default-school > /dev/null && exit 0 umask 0002 mkdir -p /srv/samba/schools/default-school chmod 777 /srv/samba/schools/default-school -mkdir -p "/lmn/media/${SUDO_USER}/share" mount -t cifs //server/default-school/ /srv/samba/schools/default-school \ -o "sec=krb5i,cruid=${SUDO_UID},user=${SUDO_USER},uid=${SUDO_UID},gid=${SUDO_GID},file_mode=0700,dir_mode=0700,mfsymlinks,nobrl,actimeo=600,cache=loose,echo_interval=10" -mount --bind /srv/samba/schools/default-school/share "/lmn/media/${SUDO_USER}/share" echo "Einbindung erfolgreich!" echo "Dieses Fenster bitte nicht schließen!" diff --git a/roles/lmn_vpn/tasks/wg_config.yml b/roles/lmn_vpn/tasks/wg_config.yml index d1bf9ce..1e42049 100644 --- a/roles/lmn_vpn/tasks/wg_config.yml +++ b/roles/lmn_vpn/tasks/wg_config.yml @@ -5,7 +5,7 @@ - wireguard - name: Check if wg_server is reachable - ansible.builtin.command: echo "Test if wg_server is reachable" + ansible.builtin.command: echo "reachable" delegate_to: wireguard_server register: result changed_when: false @@ -17,10 +17,12 @@ * server not reachable * no matching ssh-key changed_when: true - when: result.unreachable is defined and result.unreachable + when: result.stdout is not defined or result.stdout!="reachable" - name: Configure WG Server - when: result.unreachable is not defined or not result.unreachable + when: + - result.stdout is defined and result.stdout=="reachable" + - not run_in_installer|default(false)|bool block: - name: Set facts wg_clientname ansible.builtin.set_fact: diff --git a/roles/lmn_wlan/tasks/eap-tls_check-certificate.yaml b/roles/lmn_wlan/tasks/eap-tls_check-certificate.yaml index 74bc7c4..79932f0 100644 --- a/roles/lmn_wlan/tasks/eap-tls_check-certificate.yaml +++ b/roles/lmn_wlan/tasks/eap-tls_check-certificate.yaml @@ -27,7 +27,7 @@ when: cert_client_active.stat.exists - name: Check if radius-server is reachable - ansible.builtin.command: echo "Test if radius-server is reachable" + ansible.builtin.command: echo "reachable" delegate_to: radius_server register: radius_reachable changed_when: false @@ -40,12 +40,13 @@ - "* server not reachable" - "* no matching ssh-key" changed_when: true - when: radius_reachable.unreachable is defined and radius_reachable.unreachable + when: radius_reachable.stdout is not defined or radius_reachable.stdout!='reachable' - name: Issue radius certificate ansible.builtin.include_tasks: eap-tls_issue-certificate.yaml when: - - radius_reachable.unreachable is not defined or not radius_reachable.unreachable + - radius_reachable.stdout is defined and radius_reachable.stdout=="reachable" + - not run_in_installer|default(false)|bool - | ( not cert_client_active.stat.exists ) or (cert_serial.stdout | replace('serial=','') | int(base=16) ) in ( radius_crl.revoked_certificates | map(attribute='serial_number') | list ) or diff --git a/roles/lmn_wlan/tasks/eap-tls_issue-certificate.yaml b/roles/lmn_wlan/tasks/eap-tls_issue-certificate.yaml index a3258df..9e897bb 100644 --- a/roles/lmn_wlan/tasks/eap-tls_issue-certificate.yaml +++ b/roles/lmn_wlan/tasks/eap-tls_issue-certificate.yaml @@ -105,6 +105,7 @@ ansible.builtin.systemd: name: iwd.service enabled: false + failed_when: false - name: Remove deprecated NetworkManager config ansible.builtin.blockinfile: diff --git a/roles/lmn_wlan/tasks/main.yaml b/roles/lmn_wlan/tasks/main.yaml index 1fb7ec2..d5adcea 100644 --- a/roles/lmn_wlan/tasks/main.yaml +++ b/roles/lmn_wlan/tasks/main.yaml @@ -3,7 +3,6 @@ - name: Install packages related to wifi ansible.builtin.apt: name: - - systemd-resolved - firmware-realtek # for our wifi sticks - name: Provide service to enable WiFi on boot