31 dic 2009
25 nov 2009
Bad English
Tra le tante vacanze che ho trascorso in Scozia, quella del 2004 resta una delle più belle ed intense, oltre che uno di quelle in cui mi sono divertito di più!
Potrei ricordarla grazie agli scatti di Ernesto, che anche se non eravamo gnocchi come le sue modelle seminude si è prodigato con gioia nel realizzare un meraviglioso album di ricordi fotografici.
O per il George, antico e caratteristico hotel di Invereray, con ben due bar al pian terreno, centinaia di varietà di whisky, e sette caminetti.
Per il kebabbaro di Fort Williams, che pur di fare un piacere a Loris siamo finiti al cinese, più pacchiano e di certo più velenoso ancora.
Per la verde Isle Of Skye con la vecchia finta decorativa di fianco al caminetto, per esserci persi nel cuore della notte nel bel mezzo del nulla (Loch Torridon = nulla), e per la festa a Garve degli anziani dai molti tatuaggi.
O per tutti i marciapiedi presi in pieno con la anteriore destra. E quando non era il marciapiede, era il cambio della Vauxhall Zafìra: prima, seconda, e terz... oops oh no, di nuovo la prima!
Grazie al Gary del Bar Bazza di Inverness per averci invitato al party, facendoci entrare dalla porta sul retro, oltre ad un ringraziamento sentito alla polizia per averci riportato Achille smarritosi, tra le strade impregnate di nebbia e fumi al profumo di torba, lungo la sponda errata del fiume Ness.
E la festa nella hall di un albergo a Pitlochry, dove gli scozzesi volevano tagliarci la testa? E le vecchiacce che ho inzuppato involontariamente con una pozzanghera?
Niente Aberdeen o Dundee quell'anno, poco Glasgow e poco river Clyde. Ma ci siamo immersi per un paio di giorni nella magica Edimburgh. Tra tutte quante, resta la mia città preferita. E non solo per la giovane dai capelli rossi che prendeva il sole lungo la riva del Firth Of Forth, capezzoli al vento.
Potrei ricordare il viaggio del 2004 per tutto questo, ma poiché questo è un blog culturale, preferisco non divagare e concentrarmi su di un po' di cultura!
Bad English 1
Finalmente a Biggar troviamo un ristorante serio. Niente haggis, fish and chips, thai o cineserie varie.
Finalmente Loris può ordinare un buon main course di quelli da uomini veri: un'ottima Fisherman's Pie con una buona pinta di Real Ale.
Poteva la cameriera fare finta di nulla? Lei ci stava provando per davvero.
Dovevamo io e Giovanni far notare che forse c'era qualche cosa di strano? No di certo, non volevamo infierire!
Poteva Tom starsene zitto?
Tom: "Loris, are you sure? Fisherman's pee? Oh... that's another story!"
Bad English 2
Capisco gli spaghetti alla bolognese: andare in Scozia per ordinare un piatto di spaghetti è certamente deprecabile, ma capisco.
I miei dubbi riguardano invece gli spaghetti alla milanese. Che siano spaghetti allo zafferano? Spaghetti col risotto? Spaghetti con la cotoletta?
Sono uno di quei nomi italiani messi lì così, tanto per gabbare qualche pence in più agli ignari avventori scozzesi, oppure esistono per davvero anche in Italia?
Questo è ciò che non capisco!
Nonostante questo mistero, il napoletano di South Bridge ad Edimbourgh era un mago del Fish and Chips.
Il suo Take Away Restaurant era il nostro faro in mezzo al buio per quando la notte si brancolava ubriachi uscendo dal Liquid Room. O ubriachi uscendo dall'Espionage.
O dopo quella volta che siamo tornati ubriachi dal Frankenstein Pub più Espionage più Liquid Room più Finnegans Wake, oltre a svariati pub di Market Street, una prosciutto funghi e ananas, diverse extra cold pints all'Hard Rock Cafè, e qualche passeggiata lungo le meravigliose Princess e Victoria Streets. Non necessariamente in questo preciso ordine.
But that's another story, ma friend.
Quel pomeriggio eravamo ancora sobri e sinceri, mentre attendevamo con pazienza la friggitura nel grasso sintetico di pecora del nostro merluzzo con le patatine.
Una giovane scozzese, bionda oltre che carina più che mai, lega il suo cane ad un lampione e poi entra, guarda caso, proprio nel nostro take away.
Lino, viscido come una lumaca, riesce a vincere la massima onorificenza come corteggiatore nell'anno, ed ancora oggi è il detentore passato presente futuro di ogni titolo a riguardo.
Vero che di due di picche ne ho visti tanti (devo tristemente ammettere di essere un professionista in ciò) ma qui si tratta di un professionista più professionale ancora, da cui c'è solo da imparare.
Pochi secondi, ed è già un disastro. Lei esce dal locale, trascina via il suo cane, e sparisce nel mezzo della foschia lungo North Bridge. Spero ancora oggi che non si sia buttata giù di sotto.
Lino, detto Mr. Wood, si interroga: "Ma si è arrabbiata? Perché si è arrabbiata? Era una battuta simpatica, niente di che! Una cosa così, tanto per rompere il ghiaccio."
ehm... d'accordo...
"Le solo detto che il suo cane era fuggito via, così per scherzo!"
ehm... banale, ma efficace!
"Cosa ho detto di preciso? Le ho detto..."
ahia!
"YOU DOG GO HOME!"
Sorry Mr. Wood: forse BITCH era la parola che stavi cercando!
Potrei ricordarla grazie agli scatti di Ernesto, che anche se non eravamo gnocchi come le sue modelle seminude si è prodigato con gioia nel realizzare un meraviglioso album di ricordi fotografici.
O per il George, antico e caratteristico hotel di Invereray, con ben due bar al pian terreno, centinaia di varietà di whisky, e sette caminetti.
Per il kebabbaro di Fort Williams, che pur di fare un piacere a Loris siamo finiti al cinese, più pacchiano e di certo più velenoso ancora.
Per la verde Isle Of Skye con la vecchia finta decorativa di fianco al caminetto, per esserci persi nel cuore della notte nel bel mezzo del nulla (Loch Torridon = nulla), e per la festa a Garve degli anziani dai molti tatuaggi.
O per tutti i marciapiedi presi in pieno con la anteriore destra. E quando non era il marciapiede, era il cambio della Vauxhall Zafìra: prima, seconda, e terz... oops oh no, di nuovo la prima!
Grazie al Gary del Bar Bazza di Inverness per averci invitato al party, facendoci entrare dalla porta sul retro, oltre ad un ringraziamento sentito alla polizia per averci riportato Achille smarritosi, tra le strade impregnate di nebbia e fumi al profumo di torba, lungo la sponda errata del fiume Ness.
E la festa nella hall di un albergo a Pitlochry, dove gli scozzesi volevano tagliarci la testa? E le vecchiacce che ho inzuppato involontariamente con una pozzanghera?
Niente Aberdeen o Dundee quell'anno, poco Glasgow e poco river Clyde. Ma ci siamo immersi per un paio di giorni nella magica Edimburgh. Tra tutte quante, resta la mia città preferita. E non solo per la giovane dai capelli rossi che prendeva il sole lungo la riva del Firth Of Forth, capezzoli al vento.
Potrei ricordare il viaggio del 2004 per tutto questo, ma poiché questo è un blog culturale, preferisco non divagare e concentrarmi su di un po' di cultura!
Bad English 1
Finalmente a Biggar troviamo un ristorante serio. Niente haggis, fish and chips, thai o cineserie varie.
Finalmente Loris può ordinare un buon main course di quelli da uomini veri: un'ottima Fisherman's Pie con una buona pinta di Real Ale.
Poteva la cameriera fare finta di nulla? Lei ci stava provando per davvero.
Dovevamo io e Giovanni far notare che forse c'era qualche cosa di strano? No di certo, non volevamo infierire!
Poteva Tom starsene zitto?
Tom: "Loris, are you sure? Fisherman's pee? Oh... that's another story!"
Bad English 2
Capisco gli spaghetti alla bolognese: andare in Scozia per ordinare un piatto di spaghetti è certamente deprecabile, ma capisco.
I miei dubbi riguardano invece gli spaghetti alla milanese. Che siano spaghetti allo zafferano? Spaghetti col risotto? Spaghetti con la cotoletta?
Sono uno di quei nomi italiani messi lì così, tanto per gabbare qualche pence in più agli ignari avventori scozzesi, oppure esistono per davvero anche in Italia?
Questo è ciò che non capisco!
Nonostante questo mistero, il napoletano di South Bridge ad Edimbourgh era un mago del Fish and Chips.
Il suo Take Away Restaurant era il nostro faro in mezzo al buio per quando la notte si brancolava ubriachi uscendo dal Liquid Room. O ubriachi uscendo dall'Espionage.
O dopo quella volta che siamo tornati ubriachi dal Frankenstein Pub più Espionage più Liquid Room più Finnegans Wake, oltre a svariati pub di Market Street, una prosciutto funghi e ananas, diverse extra cold pints all'Hard Rock Cafè, e qualche passeggiata lungo le meravigliose Princess e Victoria Streets. Non necessariamente in questo preciso ordine.
But that's another story, ma friend.
Quel pomeriggio eravamo ancora sobri e sinceri, mentre attendevamo con pazienza la friggitura nel grasso sintetico di pecora del nostro merluzzo con le patatine.
Una giovane scozzese, bionda oltre che carina più che mai, lega il suo cane ad un lampione e poi entra, guarda caso, proprio nel nostro take away.
Lino, viscido come una lumaca, riesce a vincere la massima onorificenza come corteggiatore nell'anno, ed ancora oggi è il detentore passato presente futuro di ogni titolo a riguardo.
Vero che di due di picche ne ho visti tanti (devo tristemente ammettere di essere un professionista in ciò) ma qui si tratta di un professionista più professionale ancora, da cui c'è solo da imparare.
Pochi secondi, ed è già un disastro. Lei esce dal locale, trascina via il suo cane, e sparisce nel mezzo della foschia lungo North Bridge. Spero ancora oggi che non si sia buttata giù di sotto.
Lino, detto Mr. Wood, si interroga: "Ma si è arrabbiata? Perché si è arrabbiata? Era una battuta simpatica, niente di che! Una cosa così, tanto per rompere il ghiaccio."
ehm... d'accordo...
"Le solo detto che il suo cane era fuggito via, così per scherzo!"
ehm... banale, ma efficace!
"Cosa ho detto di preciso? Le ho detto..."
ahia!
"YOU DOG GO HOME!"
Sorry Mr. Wood: forse BITCH era la parola che stavi cercando!
Etichette:
english
23 nov 2009
Copia dinamica su memoria USB
Recentemente ho avuto l'esigenza di effettuare in automatico il backup di alcuni dati su di una memoria USB.
Sembrerebbe semplicissimo, peccato però che il nome dell'unità USB non sia fisso, ma possa cambiare a seconda dell'ordine con cui eventuali apparati USB sono collegati al sistema. Con un po' di VBS si risolve però tutto:
objDrive.DriveType vale 1 per le unità di tipo Flash. Ricercando soltanto le unità con objDrive.isReady impostato a vero si escludono eventuali unità quali lettori di card flash, nel caso in cui una flash card non sia inserita, ovviamente.
In casi particolari, dove si utilizzano molte unità USB flash, non ci sono molte possibilità di indovinare l'unità giusta: allora non ci resta che assegnare un nome al disco USB ed effettuare un filtro sul campo objDrive.VolumeName.
Sembrerebbe semplicissimo, peccato però che il nome dell'unità USB non sia fisso, ma possa cambiare a seconda dell'ordine con cui eventuali apparati USB sono collegati al sistema. Con un po' di VBS si risolve però tutto:
On Error Resume Next Set objFSO = CreateObject("Scripting.FileSystemObject") Set colDrives = objFSO.Drives Unita = "" For Each objDrive in colDrives If objDrive.isReady Then If objDrive.DriveType = 1 Then Unita = objDrive.DriveLetter End If End If Next If Unita = "" Then Wscript.Echo "Memoria USB non rilevata! Impossibile Salvare" Wscript.Quit(1) End If Wscript.Echo "Salvataggio in corso in " & Unita & ":\Backup\" objFSO.CreateFolder(Unita & ":\Backup\") Err.Clear objFSO.CopyFile "C:\Percorso\Origine.dat", Unita & ":\Backup\VaccinatiBAK.dat", True If (Err.Number > 0) Then Wscript.Echo "Errore nella copia di backup: " & Err.Description Else Wscript.Echo "Copia OK" End If
objDrive.DriveType vale 1 per le unità di tipo Flash. Ricercando soltanto le unità con objDrive.isReady impostato a vero si escludono eventuali unità quali lettori di card flash, nel caso in cui una flash card non sia inserita, ovviamente.
In casi particolari, dove si utilizzano molte unità USB flash, non ci sono molte possibilità di indovinare l'unità giusta: allora non ci resta che assegnare un nome al disco USB ed effettuare un filtro sul campo objDrive.VolumeName.
Etichette:
windows
9 nov 2009
Aprire Explorer o Finder dalla Console
In Windows sono abituato a lavorare frequentemente con la console, e spesso mi capita di dover aprire una finestra di Explorer sul percorso corrente. In questo caso, il comando start è indispensabile:
Oppure con l'ottimo Total Commander è ancora più semplice!
Il comando start è utile anche per aprire un file in automatico con il programma associato:
Il seguente comando apre una finestra del Finder nel percorso corrente:
Per aprire un programma dalla console posso utilizzare il seguente comando:
C:\Users\fede\AppData>start .Per fare l'operazione inversa, ovvero aprire una console che punta al percorso di un file o di una cartella, si può utilizzare l'utility "Open Command Window Here" delle utility PowerToys per Windows XP, oppure con il file di registro cmdhere.reg (così si impara qualcosa su come funziona la chiave HKEY_CLASSES_ROOT oppure la HKEY_CURRENT_USER\Software\Classes).
Oppure con l'ottimo Total Commander è ancora più semplice!
Il comando start è utile anche per aprire un file in automatico con il programma associato:
C:\Users\fede\Documents\Web>start index.htmlSe invece voglio aprire un file con un programma specifico devo assicurarmi che l'eseguibile sia presente nel PATH:
C:\Users\fede\Documents\Web>notepad++ index.htmltutto molto semplice. Ma per fare le stesse cose nel mondo Mac?
Il seguente comando apre una finestra del Finder nel percorso corrente:
macbook-pro-di-federico:~ federico$ open .mentre per fare l'inverso, si può installare il programma OpenTerminal per Mac.
Per aprire un programma dalla console posso utilizzare il seguente comando:
macbook-pro-di-federico:~ federico$ open /Applications/TextEdit.app
15 ott 2009
Installare l'Agente di LANDesk da remoto
Per distribuire l'agente di LANDesk esistono numerose strategie che si possono trovare nel documento Best Practices for Agent Deployment.
Spesso mi capita di dover installare velocemente un agente su di un PC remoto, ed ho quindi predisposto il seguente script batch:
Questo script lancia sul computer remoto dei comandi multipli che installano l'agente di LANDesk tramite l'utility PSEXEC.
Spesso mi capita di dover installare velocemente un agente su di un PC remoto, ed ho quindi predisposto il seguente script batch:
@echo off echo Installazione remota Agent LANDesk set /P nomepc=Nome computer^> set /P passwd=Password^> psexec \\%nomepc% -u Administrator -p %passwd% cmd /c (net use r: \\serverLD\ldlogon /user:serverLD\administrator password ^& r:\wscfg32.exe /noui /f /noreboot ^& net use r: /delete) pauseQuesto script richiede il nome del computer remoto (oppure l'indirizzo IP) e la password dell'amministratore locale! Attenzione: questa password verrà visualizzata in chiaro!
Questo script lancia sul computer remoto dei comandi multipli che installano l'agente di LANDesk tramite l'utility PSEXEC.
Etichette:
LANDesk
14 ott 2009
Ambiguità di alcune parole inglesi
Ambiguità di alcune parole inglesi.
Trecentottanta esempi di errori di traduzione, difficoltà, incomprensioni, sciocchezze e bizzarrie.
Trecentottanta esempi di errori di traduzione, difficoltà, incomprensioni, sciocchezze e bizzarrie.
Etichette:
english
12 ott 2009
Bloccare gli aggiornamenti software
Disabilitare gli aggiornamenti del sistema operativo oppure del software applicativo è in genere una pratica da evitare: un sistema aggiornato è più stabile, e molto più sicuro!
Ad oggi le poche aziende che non hanno attivato un sistema di aggiornamento automatico per il sistema operativo Windows ne pagano le conseguenze (vedi ad esempio Conficker). Ed è curioso notare che, poiché un sistema Windows aggiornato e configurato adeguatamente offre sistemi di sicurezza avanzati e difficili da aggirare, si sta assistendo ad un cambio di tendenza e l'obiettivo principale degli attacchi del malware più recente si sta spostando dal sistema operativo agli applicativi utente installati sopra.
Applicazioni che girano in modalità utente quali Flash Player, Silverlight, Acrobat Reader, Internet Explorer, Firefox e relativi plugin, sono tutte ottime candidate.... i bug non mancano mai, e se ci riflettiamo un poco perché attaccare tutto il sistema? Dati sensibili, password e quant'altro si trovano proprio dal lato utente!
Naturalmente verso questo tipo di attacchi il famigerato UAC di Windows Vista e Windows 7 spesso non può fare molto... così come può fare ben poco la richiesta di password dei vari Linux, o MacOS: il sistema è protetto, e va bene, ma i dati degli utenti forse non troppo!
Perché quindi bloccare gli aggiornamenti del software applicativo?
Ci devono essere delle ottime ragioni, ed una di queste è che gli aggiornamenti spesso e volentieri sono progettati per funzionare su computer domestici, in cui l'utente ha accesso ad Internet completo ed accede al desktop con amministrativi.
In un'azienda non tutti i PC hanno accesso ad Internet, quelli che vi accedono probabilmente dispongono di un accesso filtrato, ed anche se riescono a scaricare gli aggiornamenti, propabilmente non riescono ad installarli poiché l'utente non dispone di diritti per aggiornare il software installato.
Normalmente il software applicativo presente nei computer aziendali non è lo stesso software che può scaricare l'utente finale: in genere è preferibile distribuire versioni amministrative o aziendali oppure versioni ripacchettizzate (es. Firefox, Flash Player, e Acrobat Reader si trovano anche in versione MSI, e nel caso in cui non si trovino, basta cercare per esempio sul sito www.appdeploy.com per trovare tutto quello di cui c'è bisogno).
E normalmente il software applicativo viene configurato per non aggiornarsi automaticamente: gli aggiornamenti sono disabilitati, perché è inutile disporre di decine di updater uno per ogni servizio, quando invece sono disponibili applicazioni apposite per la distribuzione di tutti gli aggiornamenti!
Cosa fare per tutto il software che invece è stato scaricato da una versione "tradizionale" e quindi con gli aggiornamenti attivati?
In genere le informazioni di configurazione sono sparsi in qualche chiave di registro, naturalmente nella HKLM. Abbiamo bisogno quindi di un buon script WSH da eseguire all'avvio della macchina da lanciare con privilegi amministrativi.
Creiamo una nuova policy, e su Computer Configuration - Windows Settings - Scripts aggiungiamo uno script di avvio simile al seguente:
Questi sono i parametri che ho trovato in giro. Ovviamente possiamo personalizzare questo script a piacimento per supportare altri programmi oppure altre versioni. Naturalmente cerchiamo di farne buon uso!
Llo stesso identico procedimento può essere utilizzato per modificare all'avvio qualsiasi chiave di sistema oppure, se creiamo lo script lato utente, possiamo impostare le chiavi in HKEY_CURRENT_USER.
Molto utile quindi non solo per gli aggiornamenti, ma anche per poter preconfigurare ad ogni avvio una buona parte del software lato desktop.
Ad oggi le poche aziende che non hanno attivato un sistema di aggiornamento automatico per il sistema operativo Windows ne pagano le conseguenze (vedi ad esempio Conficker). Ed è curioso notare che, poiché un sistema Windows aggiornato e configurato adeguatamente offre sistemi di sicurezza avanzati e difficili da aggirare, si sta assistendo ad un cambio di tendenza e l'obiettivo principale degli attacchi del malware più recente si sta spostando dal sistema operativo agli applicativi utente installati sopra.
Applicazioni che girano in modalità utente quali Flash Player, Silverlight, Acrobat Reader, Internet Explorer, Firefox e relativi plugin, sono tutte ottime candidate.... i bug non mancano mai, e se ci riflettiamo un poco perché attaccare tutto il sistema? Dati sensibili, password e quant'altro si trovano proprio dal lato utente!
Naturalmente verso questo tipo di attacchi il famigerato UAC di Windows Vista e Windows 7 spesso non può fare molto... così come può fare ben poco la richiesta di password dei vari Linux, o MacOS: il sistema è protetto, e va bene, ma i dati degli utenti forse non troppo!
Perché quindi bloccare gli aggiornamenti del software applicativo?
Ci devono essere delle ottime ragioni, ed una di queste è che gli aggiornamenti spesso e volentieri sono progettati per funzionare su computer domestici, in cui l'utente ha accesso ad Internet completo ed accede al desktop con amministrativi.
In un'azienda non tutti i PC hanno accesso ad Internet, quelli che vi accedono probabilmente dispongono di un accesso filtrato, ed anche se riescono a scaricare gli aggiornamenti, propabilmente non riescono ad installarli poiché l'utente non dispone di diritti per aggiornare il software installato.
Normalmente il software applicativo presente nei computer aziendali non è lo stesso software che può scaricare l'utente finale: in genere è preferibile distribuire versioni amministrative o aziendali oppure versioni ripacchettizzate (es. Firefox, Flash Player, e Acrobat Reader si trovano anche in versione MSI, e nel caso in cui non si trovino, basta cercare per esempio sul sito www.appdeploy.com per trovare tutto quello di cui c'è bisogno).
E normalmente il software applicativo viene configurato per non aggiornarsi automaticamente: gli aggiornamenti sono disabilitati, perché è inutile disporre di decine di updater uno per ogni servizio, quando invece sono disponibili applicazioni apposite per la distribuzione di tutti gli aggiornamenti!
Cosa fare per tutto il software che invece è stato scaricato da una versione "tradizionale" e quindi con gli aggiornamenti attivati?
In genere le informazioni di configurazione sono sparsi in qualche chiave di registro, naturalmente nella HKLM. Abbiamo bisogno quindi di un buon script WSH da eseguire all'avvio della macchina da lanciare con privilegi amministrativi.
Creiamo una nuova policy, e su Computer Configuration - Windows Settings - Scripts aggiungiamo uno script di avvio simile al seguente:
Dim WshShell Set WshShell = WScript.CreateObject("WScript.Shell") On Error Resume Next ' disabilita aggiornamenti Adobe Acrobat WshShell.RegWrite "HKLM\Software\Policies\Adobe\Acrobat Reader\8.0\FeatureLockdown\bUpdater", 0, "REG_DWORD" WshShell.RegWrite "HKLM\SOFTWARE\Policies\Adobe\Acrobat Reader\9.0\FeatureLockdown\bUpdater", 0, "REG_DWORD" WshShell.RegWrite "HKLM\SOFTWARE\Adobe\Acrobat Reader\9.0\AdobeViewer\EULA", 1, "REG_DWORD" WshShell.RegWrite "HKLM\SOFTWARE\Adobe\Acrobat Reader\9.0\AdobeViewer\Launched", 1, "REG_DWORD" ' disabilita aggiornamenti Java WshShell.RegWrite "HKLM\SOFTWARE\JavaSoft\Java Update\Policy\EnableJavaUpdate", 0, "REG_DWORD" WshShell.RegWrite "HKLM\SOFTWARE\JavaSoft\Java Update\Policy\EnableAutoUpdateCheck", 0, "REG_DWORD" Wscript.Quit
Questi sono i parametri che ho trovato in giro. Ovviamente possiamo personalizzare questo script a piacimento per supportare altri programmi oppure altre versioni. Naturalmente cerchiamo di farne buon uso!
Llo stesso identico procedimento può essere utilizzato per modificare all'avvio qualsiasi chiave di sistema oppure, se creiamo lo script lato utente, possiamo impostare le chiavi in HKEY_CURRENT_USER.
Molto utile quindi non solo per gli aggiornamenti, ma anche per poter preconfigurare ad ogni avvio una buona parte del software lato desktop.
7 ott 2009
Chi è l'utente .Default?
Sfogliando la chiave di registro HKEY_USERS possiamo osservare che sono presenti tutte le chiavi HKEY_CURRENT_USER, organizzate per SID, di tutti gli utenti attualmente connessi al sistema.
La HKEY_CURRENT_USER di ogni utente si trova nel file NTUSER.DAT all'interno di ogni profilo. Quando un utente effettua l'accesso al computer, il sistema operativo carica il file NTUSER.DAT nella HKEY_USERS assieme a tutti gli altri utenti, ed ogni utente nella HKEY_CURRENT_USER vede soltanto le sue chiavi.
Oltre ai SID degli utenti, possiamo osservare che è presente un utente .Default. Ma chi è l'utente .Default?
Naturalmente è ragionevole pensare che l'utente .Default sia utilizzato come profilo template per i nuovi utenti: modificando le impostazioni dell'utente .Default è logico aspettarsi che tutti i nuovi utenti creati nel sistema ereditino queste impostazioni.
In effetti la scelta del nome .Default è stata infelice, e le cose vanno diversamente. Le chiavi di registro dell'utente .Default appartengono all'utente Local System, mentre il template di default per i nuovi utenti di sistema non è generalmente caricato in memoria e si trova nel percorso C:\Users\Default\NTUSER.DAT per Vista o Seven, oppure in C:\Documents and Settings\Default User\NTUSER.DAT per XP.
Per modificare le impostazioni di default è possibile caricare manualmente questo Hive in memoria, modificarlo e salvarlo, anche se questo metodo non è ufficialmente supportato.
Conviene utilizzare il buon SysPrep... oppure ho risolto il problema con un meraviglioso script WSH all'avvio.
Per approfondire: The .Default user is not the default user.
La HKEY_CURRENT_USER di ogni utente si trova nel file NTUSER.DAT all'interno di ogni profilo. Quando un utente effettua l'accesso al computer, il sistema operativo carica il file NTUSER.DAT nella HKEY_USERS assieme a tutti gli altri utenti, ed ogni utente nella HKEY_CURRENT_USER vede soltanto le sue chiavi.
Oltre ai SID degli utenti, possiamo osservare che è presente un utente .Default. Ma chi è l'utente .Default?
Naturalmente è ragionevole pensare che l'utente .Default sia utilizzato come profilo template per i nuovi utenti: modificando le impostazioni dell'utente .Default è logico aspettarsi che tutti i nuovi utenti creati nel sistema ereditino queste impostazioni.
In effetti la scelta del nome .Default è stata infelice, e le cose vanno diversamente. Le chiavi di registro dell'utente .Default appartengono all'utente Local System, mentre il template di default per i nuovi utenti di sistema non è generalmente caricato in memoria e si trova nel percorso C:\Users\Default\NTUSER.DAT per Vista o Seven, oppure in C:\Documents and Settings\Default User\NTUSER.DAT per XP.
Per modificare le impostazioni di default è possibile caricare manualmente questo Hive in memoria, modificarlo e salvarlo, anche se questo metodo non è ufficialmente supportato.
Conviene utilizzare il buon SysPrep... oppure ho risolto il problema con un meraviglioso script WSH all'avvio.
Per approfondire: The .Default user is not the default user.
Etichette:
windows
24 set 2009
LANDesk: aggiungere all'inventario chiavi di registro specifiche
Per informazioni dettagliate, visualizzare il documento How to scan custom registry informations.
Riassumendo:
- modificare il file c:\Program Files\LANDesk\ManagementSuite\ldlogon\ldappl3.template, ed aggiungere nella sezione Registry info la chiave da registrare nell'inventario;
- dalla console, andare su Tools | Reporting/Monitoring | Software License Monitoring, quindi cliccare su Make Available to All Clients.
A partire dalla prossima scansione di inventario, le informazioni comincieranno ad essere presenti.
Etichette:
LANDesk
5 set 2009
Kompoz!
Cercavo un sito web per la collaborazione musicale on-line, ed ho trovato kompoz, un vero e proprio social network per band virtuali, dove ogni utente può creare un progetto musicale, ed ogni altro può dare il suo contributo. Lo si fa per il software, perché non provare anche con la musica?
Mi sembra molto interessante! Per adesso ho creato la mia pagina, anche se al momento, senza ADSL, mi sarà molto difficile partecipare attivamente e continuativamente. In futuro speriamo che ne esca qualche cosa di interessante!
Mi sembra molto interessante! Per adesso ho creato la mia pagina, anche se al momento, senza ADSL, mi sarà molto difficile partecipare attivamente e continuativamente. In futuro speriamo che ne esca qualche cosa di interessante!
Etichette:
musica
28 lug 2009
Variabili d'ambiente nello script di Logon
Come settare le variabili di ambiente in uno script di logon?
In VBScript si può fare così:
(in questo esempio ho settato alla variabile INIAPP, relativa all'ambiente dell'utente, il valore "%USERPROFILE%\APP.INI"). Per rendere la modifica permanente, aggiungo anche la seguente riga:
Capita spesso inoltre di dover modificare il PATH di ricerca. La soluzione che utilizzo è la seguente, e mi permette di evitare di avere PATH doppi:
Suddivido il percorso originario in un array con i percorsi singoli, e con l'oggetto Scripting.Dictionary aggiungo ogni singolo percorso, senza duplicati. Poi ricompongo la stringa.
Semplice ma elegante!
In VBScript si può fare così:
Set WshShell = WScript.CreateObject("WScript.Shell") Set WshUEnv = WshShell.Environment("User") WshUEnv("INIAPP") = "%USERPROFILE%\APP.INI"
(in questo esempio ho settato alla variabile INIAPP, relativa all'ambiente dell'utente, il valore "%USERPROFILE%\APP.INI"). Per rendere la modifica permanente, aggiungo anche la seguente riga:
WshShell.RegWrite "HKCU\Environment\INIAPP", "%USERPROFILE%\APP.INI", "REG_EXPAND_SZ"
Capita spesso inoltre di dover modificare il PATH di ricerca. La soluzione che utilizzo è la seguente, e mi permette di evitare di avere PATH doppi:
Set WshShell = WScript.CreateObject("WScript.Shell") Set WshUEnv = WshShell.Environment("User") Set pp = CreateObject("Scripting.Dictionary") for each p in Split(WshUenv("PATH"), ";") AddPath p next AddPath "C:\PROGRAMMA1" AddPath "C:\ORACLE" AddPath "C:\TEST" WshUEnv("PATH") = Join(pp.Keys, ";") WshShell.RegWrite "HKCU\Environment\PATH", Join(pp.Keys, ";"), "REG_EXPAND_SZ" pp.RemoveAll Set pp = Nothing Set WshShell = Nothing Set WshUEnv = Nothing Sub AddPath(path) If Not pp.Exists(path) and Trim(path)<>"" then pp.Add path, "" End Sub
Suddivido il percorso originario in un array con i percorsi singoli, e con l'oggetto Scripting.Dictionary aggiungo ogni singolo percorso, senza duplicati. Poi ricompongo la stringa.
Semplice ma elegante!
Etichette:
windows
Mappare Condivisioni di Rete in base al Gruppo di appartenenza
Molte volte nello script di logon c'è la necessità di mappare condivisioni di rete in base ai gruppi cui appartiene un utente.
L'articolo How Can I Map Drives Based on Membership in a Group? tratto dal sito di Microsoft spiega molto bene il problema e fornisce una valida introduzione; lo script presentato però è molto semplificato. Ho cercato di estenderlo in base alle esigenze della mia azienda.
Gruppo Primario
Il codice tratto dall'articolo di Microsoft restituisce tutti i gruppi, ad esclusione del gruppo primario dell'utente:
Alla collezione MemberOf manca dunque il gruppo primario dell'utente, che generalmente è Domain Users ma potrebbe sempre essere stato modificato. Possiamo però ottenere il codice del gruppo primario con objUser.PrimaryGroupID e scorrere l'elenco dei gruppi fino a che non troviamo il gruppo con questo ID. La funzione che restituisce il nome del gruppo dato l'ID è la seguente:
Non sono soddisfatto di questa funzione, in quanto non sono riuscito a filtrare il gruppo direttamente nel CommandText e sono pertanto costretto a scorrere tutti i gruppi tramite Loop, fino a che non trovo il gruppo con il codice ID che stavo ricercando, ma.... comunque funziona.
Associazione Gruppi-Condivisioni
Tramite l'oggetto Scripting.Dictionary creo un elenco di associazioni tra gruppi e relative aree condivise, come ad esempio:
MapNetworkDrive
A questo punto posso scorrere tutto l'elenco dei gruppi cui l'utente appartiene, passando ogni singolo gruppo alla seguente procedura. Se il gruppo appartiene alla lista dei gruppi a cui è associata un'area condivisa, tale area viene montata nel disco "Unita".
Codice Finale
Il codice finale è il seguente, a cui vanno aggiunte la sub e la funzione presentate in precedenza:
Se un utente appartiene a più gruppi che dispongono di un'area associata, questo script monta tutti i percorsi di rete a partire dalla lettera O:, poi P:, Q: etc...
L'area di lavoro associata al gruppo primario verrà sempre montata come unità O:, mentre le altre aree saranno montate a seguire.
Se la stessa area di lavoro è associata a più gruppi, ed un utente appartiene a più di uno di questi gruppi, la stessa area verrà montata più volte.
Happy logging on!
L'articolo How Can I Map Drives Based on Membership in a Group? tratto dal sito di Microsoft spiega molto bene il problema e fornisce una valida introduzione; lo script presentato però è molto semplificato. Ho cercato di estenderlo in base alle esigenze della mia azienda.
Gruppo Primario
Il codice tratto dall'articolo di Microsoft restituisce tutti i gruppi, ad esclusione del gruppo primario dell'utente:
Set objSysInfo = CreateObject("ADSystemInfo") Set objNetwork = CreateObject("Wscript.Network") strUserPath = "LDAP://" & objSysInfo.UserName Set objUser = GetObject(strUserPath) For Each strGroup in objUser.MemberOf strGroupPath = "LDAP://" & strGroup Set objGroup = GetObject(strGroupPath) strGroupName = objGroup.CN Wscript.Echo strGroupName NextSe la objectUser.MemberOf contiene soltanto un gruppo questo il codice qui sopra va in errore, poiché MemberOf non è un array. Bisogna quindi distinguere se si tratta di un array oppure di un gruppo singolo in questo modo:
If isArray(objUser.MemberOf) then For Each strGroup in objUser.MemberOf strGroupPath = "LDAP://" & strGroup Set objGroup = GetObject(strGroupPath) checkGroup Unit, objGroup.CN Next Else strGroupPath = "LDAP://" & objUser.MemberOf Set objGroup = GetObject(strGroupPath) checkGroup Unit, objGroup.CN End If
Alla collezione MemberOf manca dunque il gruppo primario dell'utente, che generalmente è Domain Users ma potrebbe sempre essere stato modificato. Possiamo però ottenere il codice del gruppo primario con objUser.PrimaryGroupID e scorrere l'elenco dei gruppi fino a che non troviamo il gruppo con questo ID. La funzione che restituisce il nome del gruppo dato l'ID è la seguente:
Function GetPrimaryGroup(ByVal GroupID) Set objConnection = CreateObject("ADODB.Connection") Set objCommand = CreateObject("ADODB.Command") objConnection.Provider = "ADsDSOObject" objConnection.Open "Active Directory Provider" Set objCommand.ActiveConnection = objConnection objCommand.Properties("Page Size") = 100 objCommand.Properties("Timeout") = 30 objCommand.Properties("Cache Results") = False Set objRootDSE = GetObject("LDAP://RootDSE") strDNSDomain = objRootDSE.Get("defaultNamingContext") objCommand.CommandText = "<ldap://" & strdnsdomain & ">;" &_ "(objectClass=group);" &_ "sAMAccountName,primaryGroupToken;subtree" Set objRecordSet = objCommand.Execute Do Until objRecordSet.Eof If objRecordSet("primaryGroupToken").Value = GroupID Then GetPrimaryGroup = objRecordSet("sAMAccountName").Value Exit Do End If objRecordSet.MoveNext Loop objRecordset.Close objConnection.Close Set objRecordset = Nothing Set objConnection = Nothing End Function
Non sono soddisfatto di questa funzione, in quanto non sono riuscito a filtrare il gruppo direttamente nel CommandText e sono pertanto costretto a scorrere tutti i gruppi tramite Loop, fino a che non trovo il gruppo con il codice ID che stavo ricercando, ma.... comunque funziona.
Associazione Gruppi-Condivisioni
Tramite l'oggetto Scripting.Dictionary creo un elenco di associazioni tra gruppi e relative aree condivise, come ad esempio:
Set d = CreateObject("Scripting.Dictionary") d.Add "Finanziario", "\\server01\fs\Finanziario" d.Add "Personale", "\\server01\fs\Personale" d.Add "Legale", "\\server02\Legale"
MapNetworkDrive
A questo punto posso scorrere tutto l'elenco dei gruppi cui l'utente appartiene, passando ogni singolo gruppo alla seguente procedura. Se il gruppo appartiene alla lista dei gruppi a cui è associata un'area condivisa, tale area viene montata nel disco "Unita".
Sub checkGroup(ByRef Unita, ByVal Group) On Error Resume Next If d.Exists(Group) Then objNetwork.RemoveNetworkDrive Unita & ":" objNetwork.MapNetworkDrive Unita & ":", d(Group), False Unita = Chr(Asc(Unita) + 1) End If End Sub
Codice Finale
Il codice finale è il seguente, a cui vanno aggiunte la sub e la funzione presentate in precedenza:
On Error Resume Next Set objSysInfo = CreateObject("ADSystemInfo") Set objNetwork = CreateObject("Wscript.Network") rem *** associazioni gruppo-percorso Set d = CreateObject("Scripting.Dictionary") d.Add "Finanziario", "\\server01\fs\Finanziario" d.Add "Personale", "\\server01\fs\Personale" d.Add "Legale", "\\server02\Legale" rem *** prima unità di rete da connettere Unit = "O" rem *** utente corrente Set objUser = GetObject("LDAP://" & objSysInfo.UserName) rem *** controlla il gruppo primario *** checkGroup Unit, GetPrimaryGroup(objUser.PrimaryGroupID) rem *** controlla gli altri gruppi *** For Each strGroup in objUser.MemberOf strGroupPath = "LDAP://" & strGroup Set objGroup = GetObject(strGroupPath) checkGroup Unit, objGroup.CN Next rem *** cleanup d.RemoveAll
Se un utente appartiene a più gruppi che dispongono di un'area associata, questo script monta tutti i percorsi di rete a partire dalla lettera O:, poi P:, Q: etc...
L'area di lavoro associata al gruppo primario verrà sempre montata come unità O:, mentre le altre aree saranno montate a seguire.
Se la stessa area di lavoro è associata a più gruppi, ed un utente appartiene a più di uno di questi gruppi, la stessa area verrà montata più volte.
Happy logging on!
2 lug 2009
Inviare Check Passivi a Nagios
Nagios è un programma di monitoraggio di computer o risorse di rete che permette di inviare degli avvisi quando un nodo od un servizio non risulta attivo, oppure al ripristino del suo funzionamento.
Per il monitoraggio degli apparati è possibile utilizzare uno dei numerosi comandi predefiniti (es. ping, snmp, etc) oppure è possibile scrivere un comando personalizzato - uno script bash, perl, python o altro va benissimo, l'importante è che tale script restituisca un valore che indica se il servizio che stiamo monitorando è attivo oppure se presenta qualche problema.
Il sistema si occupa in automatico di schedulare i test, di raccogliere i risultati, e di inviare eventuali avvisi.
Oltre a questa modalità di monitoraggio in cui il Nagios effettua dei test ed attende la risposta dagli host remoti, che è detta attiva, è possibile utilizzare una seconda modalità, detta passiva, in cui sono gli host o i servizi remoti che inviano il loro stato al Nagios.
L'utilizzo più tipico consiste nel monitoraggio delle operazioni pianificate, ad esempio backup, allineamento tabelle, etc.
Un task viene eseguito, svolge il backup, l'allineamento, o quant'altro, ed al termine invia al Nagios una notifica con l'esito dell'operazione. Se il Nagios non riceve tale esito entro un certo periodo di tempo (perché il task si blocca prima di inviare l'avviso, o perché il task dura troppo a lungo) può segnalare comunque di non aver ricevuto alcuna informazione e attivare un allarme.
Il servizio può essere definito in questo modo (i parametri possono essere personalizzati a piacere):
In cui il comando check_dummy è definito nel seguente modo:
Come inviare i dati al server Nagios centrale? Esistono molti sistemi, ma il più semplice ed il mio preferito consiste nell'inviare l'esito dell'operazione direttamente al cmd.cgi che lo mette in coda agli altri eventi e lo fa processare.
Basta inviare un semplice POST HTTP al cgi che si trova in cgi-bin/cmd.cgi e siamo a posto! Come al solito il codice seguente è decisamente semplificato, e non tiene conto di ogni possibile errore o circostanza. In alternativa, è sempre possibile lanciare un buon wget --post="parametri" http://nagios/nagios/cgi-bin/cmd.cgi.
Per il monitoraggio degli apparati è possibile utilizzare uno dei numerosi comandi predefiniti (es. ping, snmp, etc) oppure è possibile scrivere un comando personalizzato - uno script bash, perl, python o altro va benissimo, l'importante è che tale script restituisca un valore che indica se il servizio che stiamo monitorando è attivo oppure se presenta qualche problema.
Il sistema si occupa in automatico di schedulare i test, di raccogliere i risultati, e di inviare eventuali avvisi.
Oltre a questa modalità di monitoraggio in cui il Nagios effettua dei test ed attende la risposta dagli host remoti, che è detta attiva, è possibile utilizzare una seconda modalità, detta passiva, in cui sono gli host o i servizi remoti che inviano il loro stato al Nagios.
L'utilizzo più tipico consiste nel monitoraggio delle operazioni pianificate, ad esempio backup, allineamento tabelle, etc.
Un task viene eseguito, svolge il backup, l'allineamento, o quant'altro, ed al termine invia al Nagios una notifica con l'esito dell'operazione. Se il Nagios non riceve tale esito entro un certo periodo di tempo (perché il task si blocca prima di inviare l'avviso, o perché il task dura troppo a lungo) può segnalare comunque di non aver ricevuto alcuna informazione e attivare un allarme.
Il servizio può essere definito in questo modo (i parametri possono essere personalizzati a piacere):
define service{ use service-template host_name myhost service_description logs freshness_threshold 93600 notification_period 24x7 check_command check_dummy!3 "Dati non ricevuti" active_checks_enabled 0 passive_checks_enabled 1 notification_interval 0 check_freshness 1 check_period 24x7 max_check_attempts 1 contact_groups contatti notification_options c,u,w,r notification_interval 0 notification_period 24x7 }
In cui il comando check_dummy è definito nel seguente modo:
define command { command_name check_dummy command_line $USER1$/check_dummy $ARG1$ }in questo esempio, Nagios attende il ricevimento di una notifica passiva, e se non riceve una notifica da più di 93600 secondi, allora esegue il comando check_dummy, che imposta lo stato del servizio ad UNKNOWN ed inserisce l'avviso che non riceve i log. Un amministratore di sistema si dovrà dunque preoccupare di approfondire il problema.
Come inviare i dati al server Nagios centrale? Esistono molti sistemi, ma il più semplice ed il mio preferito consiste nell'inviare l'esito dell'operazione direttamente al cmd.cgi che lo mette in coda agli altri eventi e lo fa processare.
Basta inviare un semplice POST HTTP al cgi che si trova in cgi-bin/cmd.cgi e siamo a posto! Come al solito il codice seguente è decisamente semplificato, e non tiene conto di ogni possibile errore o circostanza. In alternativa, è sempre possibile lanciare un buon wget --post="parametri" http://nagios/nagios/cgi-bin/cmd.cgi.
import httplib import urllib import sys argc = len(sys.argv) if (argc < 6): print "Nagios Passive Check Submit" print "Esempio:" print "nagiospcs Server \"Trasferimento Dati\" 3 \"Errore Import\" \"\"" else: data = urllib.urlencode( {"cmd_typ" : "30", "cmd_mod" : "2", "host" : sys.argv[1], "service" : sys.argv[2], "plugin_state" : sys.argv[3], "plugin_output" : sys.argv[4], "performance_data" : sys.argv[5]}) f = urllib.urlopen( "http://user:password@servernagios/nagios/cgi-bin/cmd.cgi", data) s = f.read() f.close()import httplib import urllib import sys argc = len(sys.argv) if (argc < 6): print "Nagios Passive Check Submit" print "Esempio:" print "nagiospcs Server \"Trasferimento Dati\" 3 \"Errore Import\" \"\"" else: data = urllib.urlencode( {"cmd_typ" : "30", "cmd_mod" : "2", "host" : sys.argv[1], "service" : sys.argv[2], "plugin_state" : sys.argv[3], "plugin_output" : sys.argv[4], "performance_data" : sys.argv[5]}) f = urllib.urlopen( "http://user:password@servernagios/nagios/cgi-bin/cmd.cgi", data) s = f.read() f.close()Ave.
Etichette:
python
29 giu 2009
Eliminare File Temporanei
Spesso applicazioni ed installer lasciano in giro per l'hard disk un sacco di spazzatura, dimenticandosi allegramente di cancellarla. Anche se è vero che i dischi sono sempre più capienti, e che un po' di file in eccesso non fanno poi così male come molti credono, ogni tanto vale la pena mettere un po' di ordine e di fare un poco di pulizia.
Posizioni dei file temporanei
Dove vengono creati generalmente i file temporanei? In genere vengono salvati nelle seguenti posizioni:
(i file temporanei di Internet Explorer o di altri browser preferisco non toccarli: in questo articolo voglio solo eliminare soltanto i file che si trovano nelle cartelle temporanee utilizzate dagli altri programmi).
Per spazzare via un po' di file inutili dovrebbero quindi essere sufficienti i seguenti comandi:
Giusto? Al di là del fatto che questi comandi sono particolarmente delicati (attenzione a non sbagliare il percorso!) è importante notare che questi comandi non sono sufficienti in un ambiente multiuser!
Si noti infatti che %TEMP% contiene soltanto il percorso dei file temporanei che appartengono all'utente corrente, ma ogni utente di sistema dispone della sua personale cartella temporanea!
Per svolgere bene il nostro compito, dobbiamo quindi scorrere tutte le variabili di ambiente di tutti gli utenti presenti nel sistema!
Come conoscere tutti gli utenti?
L'elenco degli identificativi degli utenti (detto SID) che dispongono di un profilo nel sistema lo si ottiene interrogando la chiave HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\ProfileList:
ed all'interno di ogni SID possiamo ottenere il percorso su disco del profilo interrogando la chiave ProfileImagePath.
Dove sono memorizzate le variabili d'ambiente?
Le variabili per l'utente corrente si trovano in HKEY_CURRENT_USER\Environment, mentre le vabili di tutti gli utenti attualmente attivi sul sistema le possiamo recuperare in HKEY_USERS\SID\Environment.
Se vogliamo fare le cose fatte bene dobbiamo scorrere le chiavi anche per tutti gli utenti che non sono attualmente attivi: in questo caso Windows non carica il profilo in memoria nella HKEY_USERS ma tutte le chiavi si trovano su disco nel file NTUSER.DAT che si trova all'interno di ogni ProfileImagePath.
Lo script
Nello script seguente ho mescolato un po' di tecniche diverse: WMI per scorrere il registro, WScript.Shell per leggere il registro in modalità non espansa (le variabili d'ambiente che contentono il percorso %USERPROFILE% escono tutte espanse con il profilo dell'utente che lancia lo script, e non va bene! Ovviamente non mi piace questo metodo, e spero di trovare una soluzione migliore), ed infine per caricare il file NTUSER.DAT in una chiave temporanea, non ho trovato nulla di meglio di lanciare dalla shell un buon REG LOAD...arh, brutto ma funzionale!
Fortuna che dopo qualche errore di codifica mi rifaccio, e per memorizzare l'elenco delle cartelle ho utilizzato un ArrayList, così come per le stringhe le espressioni regolari vanno sempre più che bene!
Come al solito il codice è brutto sporco e cattivo, inoltre in caso di errore.... be meglio verificare per bene prima di eliminare, non si sa mai! Ovviamente posso estendere questo codice, ed aggiungere i percorsi temporanei di Internet Explorer, Mozilla Firefox, oppure qualsiasi altro, basta solo conoscere la posizione di registro che indica il percorso dove sono salvati, oppure basta solo conoscere l'eventuale percorso del file di configurazione presente nel profilo.
Ah forse lo stesso risultato lo si poteva ottenere solamente con un file batch, qualche FOR e molte chiamate all'utility REG.EXE: sarebbe stato più coerente, ma sicuramente molto più illeggibile!
Attenzione
Nel caso in cui vengano utilizzati dei profili roaming, è sempre un rischio andare a toccare i profili salvati in locale, poiché si rischia di far perdere al sistema le informazioni di quale sia l'ultimo profilo utilizzato.
Posizioni dei file temporanei
Dove vengono creati generalmente i file temporanei? In genere vengono salvati nelle seguenti posizioni:
- %WINDIR%\Temp (tipicamente C:\WINDOWS\Temp)
- %TEMP% (tipicamente C:\Users\nomeutente\AppData\Local\TEMP, in Windows Vista)
(i file temporanei di Internet Explorer o di altri browser preferisco non toccarli: in questo articolo voglio solo eliminare soltanto i file che si trovano nelle cartelle temporanee utilizzate dagli altri programmi).
Per spazzare via un po' di file inutili dovrebbero quindi essere sufficienti i seguenti comandi:
DEL /F /S /Q "%WINDIR%\Temp" DEL /F /S /Q "%TEMP%"
Giusto? Al di là del fatto che questi comandi sono particolarmente delicati (attenzione a non sbagliare il percorso!) è importante notare che questi comandi non sono sufficienti in un ambiente multiuser!
Si noti infatti che %TEMP% contiene soltanto il percorso dei file temporanei che appartengono all'utente corrente, ma ogni utente di sistema dispone della sua personale cartella temporanea!
Per svolgere bene il nostro compito, dobbiamo quindi scorrere tutte le variabili di ambiente di tutti gli utenti presenti nel sistema!
Come conoscere tutti gli utenti?
L'elenco degli identificativi degli utenti (detto SID) che dispongono di un profilo nel sistema lo si ottiene interrogando la chiave HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\ProfileList:
REG QUERY "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\ProfileList
ed all'interno di ogni SID possiamo ottenere il percorso su disco del profilo interrogando la chiave ProfileImagePath.
Dove sono memorizzate le variabili d'ambiente?
Le variabili per l'utente corrente si trovano in HKEY_CURRENT_USER\Environment, mentre le vabili di tutti gli utenti attualmente attivi sul sistema le possiamo recuperare in HKEY_USERS\SID\Environment.
Se vogliamo fare le cose fatte bene dobbiamo scorrere le chiavi anche per tutti gli utenti che non sono attualmente attivi: in questo caso Windows non carica il profilo in memoria nella HKEY_USERS ma tutte le chiavi si trovano su disco nel file NTUSER.DAT che si trova all'interno di ogni ProfileImagePath.
Lo script
Nello script seguente ho mescolato un po' di tecniche diverse: WMI per scorrere il registro, WScript.Shell per leggere il registro in modalità non espansa (le variabili d'ambiente che contentono il percorso %USERPROFILE% escono tutte espanse con il profilo dell'utente che lancia lo script, e non va bene! Ovviamente non mi piace questo metodo, e spero di trovare una soluzione migliore), ed infine per caricare il file NTUSER.DAT in una chiave temporanea, non ho trovato nulla di meglio di lanciare dalla shell un buon REG LOAD...arh, brutto ma funzionale!
Fortuna che dopo qualche errore di codifica mi rifaccio, e per memorizzare l'elenco delle cartelle ho utilizzato un ArrayList, così come per le stringhe le espressioni regolari vanno sempre più che bene!
On Error Resume Next Const HKEY_LOCAL_MACHINE = &H80000002 Const HKEY_USERS = &H80000003 strComputer = "." Set objRegistry = GetObject("winmgmts:\\" & strComputer & "\root\default:StdRegProv") Set ws = CreateObject("Wscript.Shell") Set temporaryFolders = CreateObject("System.Collections.ArrayList") Set re = new RegExp Function GetTemp(ProfilePath, K, Key) On Error Resume Next Temp = ws.RegRead(K & "\" & Key & "\Environment\TEMP") If err.number = 0 Then re.Pattern = "%USERPROFILE%" Temp = re.Replace(Temp, ProfilePath) Else Temp = Null End If GetTemp = Temp On Error Goto 0 End Function strKeyPath = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList" objRegistry.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, arrSubkeys For Each objSubkey In arrSubkeys rem *** legge il percorso del profilo *** strValueName = "ProfileImagePath" strSubPath = strKeyPath & "\" & objSubkey objRegistry.GetExpandedStringValue HKEY_LOCAL_MACHINE, strSubPath, strValueName, strProfile rem *** legge il percorso della cartella TEMP *** FolderTmp = GetTemp(strProfile, "HKEY_USERS", objSubkey) if isNull(FolderTmp) Then rem *** non ha letto la chiave, quindi prova a caricare il registro da NTUSER.DAT *** ws.Run """%WINDIR%\System32\REG.EXE"" LOAD HKLM\TempHive """ & strProfile & "\NTUSER.DAT""", 7, true msgbox "Leggo " & strProfile FolderTmp = GetTemp(strProfile, "HKEY_LOCAL_MACHINE", "TempHive") msgbox "Letto " & FolderTmp ws.Run """%WINDIR%\System32\REG.EXE"" UNLOAD HKLM\TempHive", 7, true End If temporaryFolders.Add FolderTmp Next For Each folder In temporaryFolders Wscript.Echo "Percorso temporaneo da svuotare: " & folder Next
Come al solito il codice è brutto sporco e cattivo, inoltre in caso di errore.... be meglio verificare per bene prima di eliminare, non si sa mai! Ovviamente posso estendere questo codice, ed aggiungere i percorsi temporanei di Internet Explorer, Mozilla Firefox, oppure qualsiasi altro, basta solo conoscere la posizione di registro che indica il percorso dove sono salvati, oppure basta solo conoscere l'eventuale percorso del file di configurazione presente nel profilo.
Ah forse lo stesso risultato lo si poteva ottenere solamente con un file batch, qualche FOR e molte chiamate all'utility REG.EXE: sarebbe stato più coerente, ma sicuramente molto più illeggibile!
Attenzione
Nel caso in cui vengano utilizzati dei profili roaming, è sempre un rischio andare a toccare i profili salvati in locale, poiché si rischia di far perdere al sistema le informazioni di quale sia l'ultimo profilo utilizzato.
Etichette:
windows
10 giu 2009
Paradossi della Statistica
Per confrontare la puntialità delle compagnie aeree, spesso vengono pubblicate delle statistiche che aiutano i viaggiatori a scegliere la compagnia migliore.
La percentuale di puntualità di una compagnia aerea è definita come numero di voli con ritardi inferiori ai 15 minuti / numero voli totali: sembra ragionevole!
Vediamo un esempio di due compagnie aeree (tratto da un giornale fine anni '80):
Nei totali, America West viene premiata (90% di aerei puntuali contro 87%), ma se ci soffermiamo sui dettagli, Alaska Airlines svogle un lavoro migliore presso ogni singolo aeroporto!
Perché questo paradosso? Alaska Airlines vola in proporzione molto di più verso aeroporti le cui condizioni atmosferiche sono spesso peggiori (come Seattle) mentre America West viaggia principalmente a Phoenix, dove il traffico è minore ed il tempo è molto più bello!
Tratto da "Introduction to Probability" lezione 10, dal sito http://ocw.mit.edu. E così ho provato anche ad includere un foglio di calcolo di google docs all'interno di un post (uhm non era difficile, comunque).
9 giu 2009
A Tutorial on Support Vector Machines for Pattern Recognition
Quando ero un povero studente in informatica, ho trovato il documento "A Tutorial on Support Vector Machines for Pattern Recognition" di Chris Burges molto chiaro e molto utile. Posto qui il link così, nell'improbabile ipotesi di voler approfondire qualche argomento, riesco subito a trovare la pagina! ;-)
Etichette:
a.i.
Ottimizzazione per motori di ricerca
Ho dato una letta veloce alla Guida introduttiva di Google all'ottimizzazione per motori di ricerca (SEO). È sempre un piacere leggere della documentazione scritta in maniera semplice ma comunque precisa: gli argomenti trattati sono utili per i webmaster di ogni livello, molte informazioni sono semplici ma non per forza scontate. Inoltre, seguendo i link all'interno della guida, è possibile approfondire ogni tema con ulteriori dettagli.
Molto interessante anche il seguente post:
(però mi pareva di aver letto un documento molto più approfondito, solo che ora non riesco a trovarlo: forse si trova nel blog in inglese?)
26 mag 2009
Psexec: comandi multipli
Per effettuare un'installazione remota di un applicativo tramite psexec ho bisogno di connettere un'unità di rete, e quindi di lanciare un eseguibile. Come lanciare comandi multipli con un unico comando psexc? Ecco la sintassi:
psexec \\nomepc -u utente -p password cmd /c (net use r: /delete ^& net use r: \\remoto\installdir /utente:username /password:password ^& r:\install.bat ^& net use r: /delete)Lanciando i comandi singoli non va, così invece funziona perfettamente!
Etichette:
psexec
22 apr 2009
Google App Engine
Lotus Notes Sucks!

Odio Lotus Notes: ogni tanto è necessario ribadirlo. Sembra un client di posta scritto in Access. E scritto decisamente male (visto che Access mi piace)!
Non c'è nulla al suo posto, nulla come ci si aspetta, i pulsanti e le voci dei menù sembrano sparati sullo schermo con il mitra, le operazioni basilari o non funzionano, oppure sono ultra complicate, utilizzarlo quotidianamente è un inferno. Insomma cara IBM, la gente con la posta ci lavora, non ci deve mica giocare!
Sono perfettamente al corrente che Lotus non è solo un client di posta ma un ambiente di esecuzione di applicativi distribuiti. L'idea era bella ed innovativa. L'implementazione, un disastro. Argh!
Gmail!

Le alternative ci sono - e sono numerose - ma se parliamo solamente di posta, secondo la mia semplice ma autorevole opinione mi sembra quasi che Google, con la sua Gmail, sia l'unica azienda ad aver capito per davvero a che cosa serve l'E-Mail!
Una webmail più comoda di un vero client? Sembra impossibile, ma pare proprio che quei furbacchioni ci siano riusciti: la grafica è spartana ma leggera e funzionale, e la comodità di utilizzo supera oltre ogni aspettativa.
Bello raggruppare i messaggi in conversazioni (inbox e outbox, bye bye!) e perchè organizzare i messaggi in strutture gerarchiche? Basta con cartelle e sottocartelle: il Web 2.0, così come il mondo, funziona ad etichette.
Privacy?

Google Apps for Business
Un po' per provocazione, visto che non ne posso più di Lotus, ed un po'... perché mi sembra un'idea interessante, ho proposto di buttare via tutto e passare a Google Apps for Business. Se l'ha fatto la Regione Veneto, possiamo farlo anche noi: basta server mail in casa, basta hardware, software, firewall, sistemi di accesso remoto, licenze, rbl, antivirus che non si aggiorna, antispam che combina casino, dischi che si riempiono, basta consulenti esterni per ogni minimo problema! Basta anche con VMWare, anche se in fondo alla fine cominciava a piacermi!
Google fornisce numerosi servizi a pagamento per le aziende: si parte da dei semplici filtri da applicare ad una infrastruttura già esistente, fino alla completa casella di posta mantenuta remotamente presso i datacenter di Google.
I prezzi? Molto competitivi. Una protezione di base da applicare al proprio sistema esistente costa 3 $ annui a casella, e si arriva fino ai 40 $ annui per una casella completa, gestita ed amministrata dai migliori sistemisti della terra, e di ben 25GB tutti schiaffati nei sistemi segreti sparsi in giro per il pianeta.
Inoltre con Google Apps for Business vengono messe a disposizione delle API per gestire gli utenti via software: agganciarsi ad un sistema di Identity Management esistente non poteva essere più semplice!
Ovviamente la mia proposta non ha avuto successo (uhm non ancora): il Computer sulla Nuvola non è ben visto, viene inteso principalmente come una perdita di controllo sui propri sistemi informativi. Ed il fatto di non sapere con precisione a chi sono in mano i propri segreti non fa certo piacere.
Forse oggi è ancora troppo presto, si deve valutare meglio quali saranno gli impatti sulla privacy, ma la direzione che seguiremo tutti in un prossimo futuro sembra essere delineata!
Google App Engine

Sul fronte programmazione, non ci trovo molto di nuovo: tutto quello che avevo imparato sullo sviluppo Web anni fa si applica ancora, e ciò mi rallegra molto. Il Web server deve essere un Apache personalizzato, configurato con grande cura, e configurabile con semplicità tramite file di configurazione caricabili dallo sviluppatore. Il linguaggio di programmazione predefinito è Python, anche se di recente è possibile sviluppare anche in Java. I framework supportati sono numerosi, tra cui mi è saltato all'occhio Pylons che avevo già indicato come possibile oggetto di studio qualche post fa.
Il database messo a disposizione non è relazionale, ma ad oggetti, ma si interroga comunque oltre che con i propri metodi nativi, anche con la normale sintassi SQL (mi ricorda tanto InterSystems Ensemble che funziona allo stesso modo. Beh magari tutti i database ad oggetti funzionano allo stesso modo, chissà!).
Spero di scrivere presto qualche applicativo funzionante!
Conclusione!
Cosa mi ha colpito di Google App Engine?
Le applicazioni scritte per l'engine di Google dispongono di una autenticazione integrata, e chi dispone di un account Gmail per aziende può limitare l'accesso agli applicativi agli utenti della propria azienda.
La conclusione è che quando saremo pronti per spostare le nostre caselle di posta sulla nuvola, saremo pronti per spostare anche tutti i nostri applicativi sulla nuvola.
Non è davvero una rivoluzione da poco!
Conclusione 2.
Lotus Notes è ancora al suo posto. And it still sucks!
19 apr 2009
Conficker
Mentre molte aziende sono state colpite in maniera massiccia dall'infezione del worm Conficker, nella mia realtà il problema è passato quasi del tutto inosservato: d'altra parte i requisiti di sicurezza per evitare il propagarsi di un'infezione di questo tipo sono decisamente di base, e dovrebbe far riflettere il fatto che molte aziende che trattano dati personali o sensibili non siano state adeguatamente preparate ad una tale evenienza.
In ogni caso, è bene non abbassare la guardia, visto che il Conficker è un worm che non perdona alcuna leggerezza!
Per tutte le informazioni relative al worm vedere questo articolo: "Considerazioni per un efficace contenimento dell'infezione Conficker.B".
Uno dei problemi principali consiste nell'individuare quali siano le macchine infette. Fortunatamente sono disponibili numerosi tool di scansione della rete in grado di rilevare eventuali sistemi infetti (vedere Conficker Remote Scanners), tra i quali è presente anche nmap.
La sintassi per controllare una macchina od una rete remota è la seguente:
nmap -PN -T4 -p139,445 -n -v --script smb-check-vulns,smb-os-discovery --script-args safe=1 [targetnetworks]
Bisogna comunque tenere in considerazione il fatto che molti pc potrebbero essere spenti od essere collegati alla rete solo saltuariamente, e purtroppo avere un inventario esatti di tutti i pc che "mancano all'appello" non è sempre facile. Ho pensato quindi di far girare saltuariamente il seguente script su di un domain controller:
@echo off
for /f "tokens=4 delims=: " %%a in ('netstat -na^|find "ESTABLISHED"') do (
nmap -PN -T4 -p139,445 etc. %%a >> scan_%%a
)
Questo script estrae tutti gli indirizzi IP che hanno una connessione correntemente aperta con il domain controller, ed effettua una scansione remota sugli indirizzi rilevati.
Certo il rischio è quello di effettuare numerose scansioni allo stesso indirizzo IP, ed il rischio è che alcune connessioni possano venire allegramente ignorate (meglio un windump piuttosto di un netstat, se non vogliamo farci sfuggire nulla). Naturalmente se sarà necessario, sono pronto a modificare lo script per renderlo più funzionale!
Ah un po' di informazioni sul comando for si trovano a questa pagina http://www.ss64.com/nt/for.html.
Etichette:
sicurezza
6 apr 2009
Drupal: Integrazione con Active Directory
Drupal dispone di alcuni moduli per l'integrazione con LDAP:
- ldapauth: permette agli utenti di autenticarsi su dei server LDAP
- ldapgroups: permette di utilizzare i gruppi LDAP come ruoli di Drupal
- ldapdata: permette l'accesso in lettura/scrittura ad un server LDAP
I moduli di cui ho bisogno sono ldapauth e ldapgroups.
La procedura di installazione di un nuovo modulo è molto semplice: si scarica il modulo, lo si estrae nella cartella modules, si lancia la scansione dei nuovi moduli collegandosi all'indirizzo http://mysite/update.php e lo si attiva dalla pagina http://mysite/admin/build/modules .
La configurazione di LDAP Authentication per Active Directory è la seguente:
- Nome: inserire il nome del proprio dominio
- LDAP Server: inserire il nome del PDC
- Porta: 389 (funziona anche con il protocollo sicuro? è da provare!)
- Base DNs: inserire la OU dove si trovano gli utenti, ad esempio OU=Utenti,DC=dominio,DC=dom
- UserName attribute: sAMAccountName
- DN for non-anonymous search: inserire un utente che ha privilegi di lettura del dominio, nel formato username@dominio.dom
- inserire la password di questo utente
La configurazione di LDAP Grouops, se si vogliono utilizzare i gruppi di Active Directory, è la seguente:
- spuntare la casella "Groups are specified by LDAP attributes"
- il nome dell'attributo da inserire è memberOf
Se tutto va a buon fine, da questo momento in poi è possibile definire i permessi di ogni gruppo di Active Directory all'interno di drupal.
Etichette:
web
29 mar 2009
CMS per Intranet: Drupal?
Quando mi occupavo di applicativi Web per l'intranet aziendale, il mio strumento di sviluppo preferito era HTML::Mason, con cui si potevano creare pagine Web dinamiche con codice perl inserito all'interno delle pagine HTML.
Il suo punto di forza principale, oltre all'enorme libreria di moduli perl di buona qualità, è sempre stato il concetto di ereditarietà, che permette di creare sistemi di template in maniera molto elegante mediante il riutilizzo di componento condivise.
Sono anni che non sviluppo più per il Web, e non so se al giorno d'oggi HTML::Mason sia uno strumento ancora al passo con i tempi: come si comporta con AJAX? Esistono delle librerie integrate? Si può lavorare con la libreria GWT?
E se volessi sviluppare in Python, perché è più bello ed oggi è più di moda, esistono strumenti di sviluppo basati sugli stessi concetti di ereditarietà? Forse Pylons, ma non ho ancora avuto modo di provarlo: ci sono molti argomenti che mi piacerebbe approfondire, ma magari se ne parla nella prossima vita.
Quello di cui ho bisogno in questo momento è di uno strumento veloce, ben progettato, estensibile, per la pubblicazione di una intranet aziendale. I contenuti da distribuire sono pagine informative generiche, link, documenti, notizie, e - se possibile - qualche piccolo applicativo. Insomma ho bisogno di un CMS!
Volevo evitare di utilizzare uno strumento scritto in PHP, ma alla fine il CMS che mi è piaciuto di più è Drupal (ma perché ha un nome così brutto?): nel giro di poche ore sono riuscito a familiarizzare con lo strumento ed a creare la struttura del sito pulita ed ordinata. Come programmatore non mi piace come è stato implementato il sistema degli URL, ma il risultato finale è ottimo. Gli argomenti che devo approfondire sono i seguenti:
- è integrabile in Active Directory o LDAP? Non voglio dover creare un altro database di utenti aziendali!
- si possono scrivere degli applicativi custom da integrare all'interno della struttura?
- è possibile creare una gerarchia di contenuti protetti da ACL?
Etichette:
web
18 feb 2009
Browsing di Active Directory tramite Recordset
Esistono molte utility per effettuare il browsing di Active Directory, e che permettono di esportare i risultati di una interrograzione in svariati formati, tra cui testo, CSV, Excel, etc.
Spesso ho bisogno di fare delle elaborazioni particolarmente approfondite sui dati estratti, ed allora mi risulta molto comodo lavorare direttamente con Microsoft Access. La lettura di Active Directory tramite l'utilizzo di un Recordset pertanto è l'ideale!
Spesso ho bisogno di fare delle elaborazioni particolarmente approfondite sui dati estratti, ed allora mi risulta molto comodo lavorare direttamente con Microsoft Access. La lettura di Active Directory tramite l'utilizzo di un Recordset pertanto è l'ideale!
Function LeggiAD() Dim adoConnection As New ADODB.Connection Dim adoCommand As New ADODB.Command Dim adoRecordset As New ADODB.Recordset Dim objRootDSE As Object Dim strDNSDomain As String Set adoConnection = New ADODB.Connection adoConnection.Provider = "ADsDSOOBject" adoConnection.Open ("Active Directory Provider") Set adoCommand.ActiveConnection = adoConnection Set objRootDSE = GetObject("<ldap://RootDSE/>"> strDNSDomain = objRootDSE.Get("defaultNamingContext") adoCommand.CommandText = "<ldap://" & strDNSDomain & >;" & _ "(&(objectCategory=person)" & _ "(objectClass=user));" & _ sAMAccountName,cn;subtree" adoCommand.Properties("Page Size") = 100 adoCommand.Properties("Timeout") = 30 adoCommand.Properties("Cache Results") = False Set adoRecordset = adoCommand.Execute Do Until adoRecordset.EOF rem fai qualcosa con adoRecordset("sAMAccountName").Value rem fai qualcosa con adoRecordset("cn").Value adoRecordset.MoveNext Loop adoRecordset.Close adoConnection.Close Set adoConnection = Nothing Set adoCommand = Nothing Set objRootDSE = Nothing Set adoRecordset = Nothing End FunctionQuesto codice scorre tutti gli utenti presenti in Active Directory (filtrati da objectCategory=person e da objectClass=user) ed estrae i campi sAMAccountName e cn: i dati restituiti potrebbero poi essere inseriti in un altra tabella, o potrebbero essere elaborati in altro modo. In genere utilizzo questo codice come base di partenza, e lo personalizzo a seconda delle necessità!
12 feb 2009
Modifica ACL tramite script
Spesso mi capita di dover mantenere una struttura di cartelle di Windows che hanno delle ACL personalizzate con un livello di dettaglio molto elevato. Quando i permessi cominciano a diventare complessi lo strumento standard di Windows diventa scomodo ed è facile commettere degli errori.
L'utility Xcacls.exe, che si scarica dal sito della Microsoft, può essere di grande aiuto in tutti questi casi. Ho preparato uno script batch che richiama questa utility, leggendo da un file di testo con l'elenco delle cartelle e delle relative ACL da impostare ad ognuna di esse:
esempio di elencoacl.txt:
con il seguente impostaacl.cmd:
L'utility Xcacls.exe, che si scarica dal sito della Microsoft, può essere di grande aiuto in tutti questi casi. Ho preparato uno script batch che richiama questa utility, leggendo da un file di testo con l'elenco delle cartelle e delle relative ACL da impostare ad ognuna di esse:
esempio di elencoacl.txt:
"c:\sede\ced";"DOMAIN\user1:C" "DOMAIN\user2:R" "c:\sede\personale";"DOMAIN\user3:C" "DOMAIN\user4:R" "c:\sede\personale\dirigenza";"DOMAIN\user3:C" "c:\sede\personale\pub";"DOMAIN\Everyone:R" "c:\sede\tecnico";"DOMAIN\user4:C" "DOMAIN\user5:C" "c:\sede\tecnico\progetti";"DOMAIN\user4:R" "c:\sede\tecnico\lavori";"DOMAIN\user5:R"etc...
con il seguente impostaacl.cmd:
set LETTURA="DOMAIN\leggi:R" set SCRITTURA="DOMAIN\fede:C" set FULL="BUILTIN\Administrators:F" "NT AUTHORITY\SYSTEM:F" for /F "tokens=1,2 delims=;" %%a in (elencoacl.txt) do ( xcacls %%a /T /G %FULL% %LETTURA% %SCRITTURA% %%b /Y @if ERRORLEVEL 1 ( echo Errore set ACL directory %%a pause ) )Questo script batch legge in sequenza tutte le righe del file elencoacl.txt, ed imposta ricorsivamente ad ogni cartella i permessi associati. Fare attenzione alle cartelle innestate: questo script non è molto "furbo" e ripete le impostazioni più volte. Verificare che l'ordine delle cartelle sia corretto!
2 feb 2009
Firma Digitale
La firma digitale è un procedimento che, a partire da un documento informatico e da alcune informazioni associate ad una persona, produce un nuovo oggetto informatico firmato che attesta la volontà della persona di sottoscrivere il documento originario.
Il procedimento che viene applicato al documento da firmare si basa sulla crittografia a chiave asimmetrica, e per avere valore legale equivalente alla firma autografa deve soddisfare dei particolari requisiti.
Crittografia
La crittografia è nata per trasmettere messaggi tra un mittente ed un destinatario in modo sicuro, utilizzando però un canale di trasmissione non sicuro. Un sistema di crittografia serve ad offuscare i messaggi e renderli illeggibili da chiunque non disponga della chiave per decifrarli.
Nella crittografia a chiave simmetrica la chiave che si utilizza per cifrare i messaggi è la stessa chiave che serve a decifrarli.
Naturalmente mittente e destinatario hanno la necessità di scambiarsi in qualche modo la chiave, e per farlo devono utilizzare un canale di trasmissione sicuro; ma se dispongono di un canale sicuro, per quale motivo non utilizzano esclusivamente questo canale anche per i messaggi? Perché il canale sicuro potrebbe essere molto costoso, oppure potrebbe essere disponibile solamente in intervalli di tempo limitati (ad es. a volte ci si deve trovare di persona per scambiarsi le chiavi).
Quando mittenti e destinatari cominciano a diventare numerosi, oppure quando non si conoscono di persona, la crittografia a chiave simmetrica comincia a mostrare i suoi limiti.
Crittografia Asimmetrica
La crittografia a chiave asimmetrica utilizza invece due chiavi diverse per le operazioni di cifratura e decifratura, permettendo di semplificare il compito di distribuzione delle chiavi. Queste due chiavi sono associate tra di loro e dispongono di una proprietà che le rende molto utili: tutti i messaggi cifrati con una chiave possono essere decifrati soltanto con l'altra chiave, e viceversa. Dal punto di vista logico, queste chiavi funzionano in modo simmetrico. Asimmetrico è l'utilizzo che se ne fa: poiché da una chiave non è possibile ricavare la sua chiave associata, è possibile rilasciare pubblicamente una chiave, la quale prende il nome di chiave pubblica, mentre l'altra chiave, che viene mantenuta segreta, prende il nome di chiave privata.
Per inviare un messaggio sicuro ad un determinato destinatario, è necessario ottenere la sua chiave pubblica e cifrare il messaggio con tale chiave: solamente il destinatario legittimo è in grado di decifrarlo, poiché è l'unico che possiede la sua chiave privata.
ma tutto questo che cosa c'entra con la firma?
Cifrando un messaggio con la chiave pubblica, solamente il destinatario che dispone della chiave privata è in grado di decifrare il messaggio. Questo è utile per spedire dei messaggi offuscati ad un destinatario, ma che cosa c'entra tutto questo con la firma?
Applicando lo stesso ragionamento al contrario, se un messaggio è decifrabile tramite una chiave pubblica abbiamo la garanzia che esso sia stato cifrato dalla persona a cui è associata tale chiave, poiché è l'unica che possiede la relativa chiave privata.
Certificati
Tutto così semplice? Naturalmente no!
Per scrivere un messaggio sicuro ad un destinatario devo per prima cosa ottenere la sua chiave pubblica; ma come faccio ad essere certo: 1. che il destinatario sia proprio chi mi dice di essere, e 2. che la chiave pubblica, sia proprio la sua?
Lo stesso discorso naturalmente vale per il procedimento inverso: per essere certo che un messaggio sia stato cifrato da un utente utilizzando la sua chiave privata, devo essere sicuro di disporre esattamente della sua chiave pubblica.
Scopo dei certificati digitali è proprio di garantire che una chiave pubblico sia associato alla vera identità del soggetto che la rivendica come propria. Un certificato digitale è un documento, firmato elettronicamente da un'autorità di certificazione fidata, che associa una chiave pubblica con un'identità.
Ovviamente per verificare se il certificato digitale è valido, è necessario disporre della chiave pubblica del certificatore: ma gli enti certificatori fidati sono pochi, e le loro chiavi pubblice possono essere distribuite agevolmente tramite canali sicuri (es. generalmente vengono installate con il sistema operativo).
Dispositivi sicuri
Affinché il sistema della cifratura o della firma funzioni correttamente, è indispensabile garantire che la chiave privata sia mantenuta davvero privata. Se la chiave è memorizzata su di un file su disco o su di una memoria di massa, c'è sempre il rischio che venga in mano a terzi non autorizzati al suo utilizzo. Per evitare questo rischio è necessario utilizzare dei dispositivi di firma sicuri, dei dispositivi cioè che dispongono di una chiave privata la quale, una volta generata, non può essere esportata all'esterno.
Una smart card è un dispositivo di questo tipo: al suo interno contiene infatti una chiave privata che non può essere esportata, e dispone di un chip che effettua le operazioni crittografiche utilizzando la chiave memorizzata all'interno.
Requisiti per la firma digitale
In base alla normativa vigente, la firma forte è l'unica firma che attribuisce al documento informatico una valenza probatoria, e prevede la presenza di una Certification Authority iscritta all'albo dell'AIPA e l'utilizzo di un dispositivo di firma sicuro. La firma digitale è un tipo di firma forte.
Una firma che non possiede i requisiti precedenti è detta firma debole: la valenza probatoria del documento firmato tramite firma debole è soggetta alla discrezionalità del giudice.
Impronta del documento
L'impronta è un processo tramite il quale è possibile ottenere da un oggetto informatico di dimensione qualsiasi una sequenza di bit a lunghezza fissa (es. 128 o 160 bit). Visto che l'impronta ha lunghezza fissa mentre l'oggetto di origine può avere qualsiasi lunghezza, è naturalmente possibile ottenere delle collisioni, ovvero più oggetti diversi possono avere la stessa firma. Un algoritmo che calcola le impronte dei documenti è sicuro se non permette di ottenere facilmente, data un'impronta, un oggetto che possa generarla.
Ridurre documenti di qualsiasi dimensione ad una stringa di bit molto corta permette di effettuare calcoli molto più veloci rispetto a quelli necessari nel caso in cui l'operazione dovesse effettuarsi sul documento intero.
Procedura di generazione di un documento firmato
Il titolare di una coppia di chiavi può firmare digitalmente un documento adottando la seguente procedura:
- calcola l'impronta del documento
- esegue la cifratura dell'impronta utilizzando la sua chiave privata
- allega il documento in chiaro
- allega l'impronta cifrata del documento
- allega il certificato rilasciato dall'autorità di certificazione
- accede al certificato del mittente, contenuto nella busta
- verifica tramite l'autorità di certificazione che il certificato non sia stato revocato o sospeso
- decifra l'impronta del documento con la chiave pubblica del mittente
- calcola l'impronta del documento ricevuto
Vulnerabilità
Un dispositivo di firma quale la smart card è un dispositivo sicuro. Il PC che calcola l'impronta del documento invece è potenzialmente insicuro: come si può essere certi che l'impronta firmata dalla smart card sia esattamente l'impronta del documento visualizzato ed effettivamente scelto dall'utente?
Altri problemi potrebbero riguardare documenti non statici che contengono istruzioni o codici eseguibili, ma tali documenti sono esclusi dalla validità della firma secondo la normativa vigente.
Infine è possibile, almeno teoricamente, creare documenti ambigui che sono validi in più formati. Si suppone però che anche questi documenti siano esclusi dalla validità della firma.
Etichette:
firma digitale,
sicurezza
Installazione remota di .msi tramite PsExec
Per effettuare l'installazione da remoto di un pacchetto .msi è possibile utilizzare il comando psexec con la seguente sintassi:
psexec -u username -p password \\target -s -d msiexec /i "\\percorso_del_pacchetto.msi" /qbNaturalmente bisogna assicurarsi che l'utente username disponga dei privilegi di installazione software nella macchina target (tipicamente deve essere un amministratore). Inoltre se il pacchetto da installare si trova in un percorso di rete, l'utente username deve avere accesso alle risorse di rete, pertanto un amministratore locale della macchina potrebbe non bastare. Un amministratore di dominio invece dovrebbe funzionare sempre, ma in alternativa è possibile copiare il pacchetto nella macchina target, ed utilizzare il percorso locale.
31 gen 2009
27 gen 2009
Last.fm API e Python
Il mio primo programma Python non è certamente un esempio da inserire in un manuale di stile, ma non era nemmeno quella l'intenzione; ci tenevo a scrivere qualcosa che fosse utile e che avesse risultati pratici fin da subito.
Con piccole variazioni al codice ho potuto individuare i brani doppi, ho potuto correggere alcuni titoli errati, ho potuto individuare gli artisti che comparivano "sdoppiati" a causa del tag artistsortorder mancante.
Ed ora, che cosa resta?
Ho pensato che sarebbe stato interessante sistemare anche il genere musicale...
Gli utenti inoltre possono aggiungere dei "tag", ovvero delle etichette, agli artisti, agli album, alle canzoni che ascoltano. Da questi tag è possibile ottenere molte informazioni, tra cui il genere musicale di un artista. Ma come si possono estrarre queste informazioni?
Con piccole variazioni al codice ho potuto individuare i brani doppi, ho potuto correggere alcuni titoli errati, ho potuto individuare gli artisti che comparivano "sdoppiati" a causa del tag artistsortorder mancante.
Ed ora, che cosa resta?
Ho pensato che sarebbe stato interessante sistemare anche il genere musicale...
Last.fm
Last.fm è un social network di utenti accomunati dalla passione per la musica. Una caratteristica che lo rende interessante è la funzione di scrobbling: di ogni utente viene creato un profilo dettagliato che comprende tutti i brani ascoltati tramite l'apposita radio oppure tramite un plugin installato nel proprio player.Gli utenti inoltre possono aggiungere dei "tag", ovvero delle etichette, agli artisti, agli album, alle canzoni che ascoltano. Da questi tag è possibile ottenere molte informazioni, tra cui il genere musicale di un artista. Ma come si possono estrarre queste informazioni?
Last.fm API
Fortunatamente Last.fm mette a disposizione dei Web Services attraverso i quali è possibile estrarre tutte le informazioni presenti sul sito. Dato per scontato che non è sempre precisa (il "tag" è un'etichetta generica, che non sempre coincide col genere musicale), la funzione artist.getTopOfTags sembra proprio avvicinarsi il più possibile a quanto stavo cercando.Il codice
import sys import win32com.client import httplib import urllib import xml.dom.minidom dic = dict() def artistGetTopOfTags(artista): artist_url = u"http://ws.audioscrobbler.com/2.0/?method=artist.gettoptags&artist=%s&api_key=b25b959554ed76058ac220b7b2e0a026" url = artist_url % urllib.quote(artista.encode('utf8')) dom=xml.dom.minidom.parse(urllib.urlopen(url)) genre="" for tag in dom.getElementsByTagName('tag'): name = "" count = "" for child in tag.childNodes: if child.nodeName == "name": name = child.firstChild.nodeValue if child.nodeName == "count": count = child.firstChild.nodeValue if count=="100": genre = name return genre.title() def genere(artista): if not artista in dic: dic[artista]=artistGetTopOfTags(artista) print artista return dic[artista] def main(*args): itunes = win32com.client.Dispatch("iTunes.Application") mainLibrary = itunes.LibraryPlaylist tracks = mainLibrary.Tracks numTracks = tracks.Count n = 1; while n <= numTracks: currTrack = tracks.Item(n) if genere(currTrack.Artist) != "": try: currTrack.Genre = genere(currTrack.Artist) except: print "eccezione!" n+=1 if __name__ == '__main__': sys.exit(main(*sys.argv))va bene, le eccezioni dovranno essere gestite meglio, e va bene, il genere musicale non è sempre corretto. Però i portali Web che mettono a disposizione delle funzioni tramite Web Services sono sempre più numerosi (es. Google, Yahoo Weather, etc...) e mi pareva interessante porre le basi per iniziare ad utilizzarli. Sembra che il metodo più pythoniano di parserizzare un file XML consiste nell'utilizzare la libreria ElemenTree, e non la libreria DOM standard... bene vedremo di approfondire anche questo!
21 gen 2009
Aggiornare la libreria di iTunes con Python
Visto che la mia libreria di iTunes non ne voleva sapere di aggiornarsi correttamente, nemmeno utilizzando il buon iTunes Library Updater, ho pensato di approfittare di questo piccolo ma fastidioso inconveniente per iniziare a conoscere - finalmente - il linguaggio di programmazione Python.
Prerequisito 1 - Python!
Quale distribuzione di Python utilizzare? Poiché l'ambiente ActiveState Perl mi è molto familiare, mi sembrava naturale utilizzare ActiveState Python, ma ho notato che gli sviluppatori di Google, nel canale Google Code, preferiscono utilizzare la versione ufficiale tratta dal sito www.python.org e allora... non so ancora perché, non so se e quando lo scoprirò, ma ho deciso di iniziare anch'io con questa versione: migliaia di sviluppatori Google non possono sbagliare!
Prerequisito 2 - Apple SDK
iTunes per Windows è controllabile tramite interfaccia COM: sul sito della Apple è gentilmente messo a disposizione il software developer kit con la documentazione per l'interfaccia COM di iTunes.
Prerequisito 3 - libreria tagging MP3
Dopo anni di programmazione in Perl, sono giunto alla conclusione che le mie prime impressioni erano fin troppo vere: si tratta di un linguaggio brutto, sporco e cattivo. Ciò che lo rende comodo, ma non solo comodo, oserei dire quasi meraviglioso, è la sterminata libreria di moduli, generalmente di ottima qualità, progettati da progettisti degni di tale nome, che risolvono praticamente tutti i problemi della terra.
E per Python, esiste qualcosa di analogo?
Non lo so ancora, e quindi vai con google: il modulo Mutagen sembra proprio quello che stavo cercando, e se lo utilizzano con successo gli amici della comunità MusicBrainz, allora lo posso utilizzare con successo anch'io. Forse code.google.com è (o diventerà) il repository di riferimento per i moduli Python? Forse l'intenzione è proprio quella: vedremo!
Il codice!
Ho ancora molto dubbi, ma copiando un po' di qua un po' di là, ecco finalmente il mio primo programma Python bello e funzionante:
import win32com.client from mutagen.mp3 import MP3 from mutagen.easyid3 import EasyID3 import mutagen.id3 itunes = win32com.client.Dispatch("iTunes.Application") mainLibrary = itunes.LibraryPlaylist tracks = mainLibrary.Tracks numTracks = tracks.Count n = 1 v = 0 while n <= numTracks: currTrack = tracks.Item(n) location = win32com.client.CastTo(currTrack,'IITFileOrCDTrack').Location if ((currTrack.Artist == "") or (currTrack.Name == "")): try: m = MP3(location, ID3=EasyID3) if m.has_key('artist'): currTrack.Artist = m['artist'][0] if m.has_key('album'): currTrack.Album = m['album'][0] if m.has_key('title'): currTrack.Name = m['title'][0] if m.has_key('tracknumber'): currTrack.TrackNumber = m['tracknumber'][0] if m.has_key('date'): currTrack.Year = m['date'][0] if m.has_key('genre'): currTrack.Genre = m['genre'][0] v += 1 except mutagen.id3.error: print "Error" continue n+=1 print "Brani aggiornati: " + str(v)
Questo programma scorre tutta la libreria iTunes, ed aggiorna il nome dell'artista, il titolo dell'album e del brano, il numero di traccia, la data (uhm forse bisogna estrarre solo l'anno), ed il genere musicale, leggendoli direttamente dai tag del file MP3, per tutti i brani in cui l'artista oppure il brano sono vuoti.
Brutto, sporco, probabilmente buggato, con un cast misterioso e ancora molti perché... ma funzionale: per adesso è un buon inizio!
weRock!
Ho deciso di creare questo blog per raccogliere informazioni che mi possono essere utili e che vorrei poter ricercare in seguito. Non so se potranno essere utili anche a qualcun altro... ma le pubblico lo stesso, non si sa mai!
Iscriviti a:
Post (Atom)