Newsgroup: it.comp.lang.visual-basic
Titolo: [VB6] SetSystemTime e privilegi

Ciao,
avrei bisogno di una delucidazione a proposito dell'impostazione della
data/ora da programma.
Questo codice di esempio, che imposta l'ora a 00:
-------------------------------
Private Type SYSTEMTIME
    wYear As Integer
    wMonth As Integer
    wDayOfWeek As Integer
    wDay As Integer
    wHour As Integer
    wMinute As Integer
    wSecond As Integer
    wMilliseconds As Integer
End Type
Private UTCSysTime As SYSTEMTIME
Dim lReturn As Long
Call GetSystemTime(UTCSysTime) 'Preleva l'ora UTC attuale
UTCSysTime.wHour = 0 'Imposta l'ora alle 00
lReturn = SetSystemTime(UTCSysTime) 'Esegue il cambio dell'ora
--------------------------------
..funziona perfettamente sotto Windows XP (loggato come amministratore), ma
sotto Vista mi da dei grattacapi. Su Vista, infatti, sebbene io sia loggato
come amministratore, SetSystemTime restituisce 0, ossia fallisce il richiamo
alla funzione, a causa dei privilegi mancanti.
Se, sempre loggato come amministratore, eseguo il programma cliccando di
destro sull'icona e selezionando "esegui come amministratore" allora
funziona.
Chi mi spiega questa "finezza" ?

 ha scritto nel messaggio 
news:4af025da$1...@news.x-privat.org...

In Vista quello che appare come 'amministratore' ï¿½ in effetti un utente con 
privilegi diversi dal vero amministratore del pc (che trovi fra gli utenti). 
Molti sviluppatori infatti aboliscono l'amministratore predefinito ma cosï¿½ 
rinunciano anche ad alcune sicurezze (che in effetti un amministratore non 
vuole, in genere). Va anche detto che le applicazioni dovrebbero venir 
testate su pc con un livello di accesso inferiore all'amministratore, 
proprio per evidenziare comportamenti che altrimenti si avrebbero solo sul 
pc del cliente. Nello specifico caso, puoi risolvere il porblema eseguendo 
il logon di windows come amministratore, ma se poi distribuisci il programma 
avrai problemi simili. La soluzione migliore sarebbe quella di far 
impersonare al processo un utente che abbia i privilegi per eseguire 
l'operazione (puoi vedere le API LogonUser, ImpersonateLoggedOnUser, 
RevertToSelf)
Stefano

 Stefano
Grazie per l'informazione Stefano. Ecco spiegato il perch� del comportamento
diverso tra logon come quello che credevo essere un amministratore e
lanciare il programma come amministratore con il click di destro.
Guardo alle API che mi hai segnalato, anche se mi risulta difficile a
livello mentale pensare a come sia possibile far fare al programma
un'operazione che richiede i diritti di amministratore (cambio dell'ora) se
viene lanciato come utente "normale".

 Chi mi spiega questa "finezza" ?
In pratica anche se sei *loggato* come amministratore in Vista, i programmi 
che avvii non hanno privilegi elevati a meno che non li richiedano 
esplicitamente, con "esegui come admin" dalla shell di vista, o 
implicitamente, indicandolo in un opportuno file .manifest associato.
In entrambi casi prima dell'esecuzione comparir� il classico "elevation 
prompt".
Info sul manifest: 
http://msdn.microsoft.com/en-us/library/bb756929.aspx
Bye
Raf

 Info sul manifest: 
http://msdn.microsoft.com/en-us/library/bb756929.aspx
Grazie della dritta Raf. Il discorso del Manifest � interessante.


Anche perch� ho paura che non vi siano tanti altri modi.
Infatti se hai avviato un programma senza privilegi elevati, non � poi 
nemmeno possibile che questo se li "autoconceda" liberamente senza 
interazioni (elevation prompt) con l'utente.
E questo pu� avvenire solo al momento dell'avvio del programma (cos� almeno 
ho capito, ma se qualcuno ha delle info diverse ben venga).
Ciao
Raf 

 ho capito, ma se qualcuno ha delle info diverse ben venga).
Sto leggendo come fare un manifest esterno, ma lo strumento mt.exe che viene
consigliato � un ginepraio di parametri...


Mah, io non ho mai avuto bisogno di usare alcuno strumento: i .manifest me 
li creo a mano a partire da un template fisso.
Tipo:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
    version="1.0.0.0"
    processorArchitecture="X86"
    name="MyProgram"
    type="win32"
/>
<description>My Program</description>
 <!-- Uncomment this block to support XP Themes (a call to 
InitCommonControls is required)
   Make also sure that manifest size is multiple of 4 bytes, if it has to be 
embedded
   in a resource file.
 <dependency>
  <dependentAssembly>
   <assemblyIdentity
    type="win32"
    name="Microsoft.Windows.Common-Controls"
    version="6.0.0.0"
    processorArchitecture="X86"
    publicKeyToken="6595b64144ccf1df"
    language="*"
   />
  </dependentAssembly>
 </dependency>
 -->
  <!-- Identify the application security requirements. -->
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel
          level="requireAdministrator" />
        </requestedPrivileges>
       </security>
  </trustInfo>
</assembly>
(Nota: il manifest contiene eventualmente anche le info necessarie per 
supportare i temi di XP)
Quando devo "embeddarlo" nell'exe utilizzo uno script RC da cui (tramite il 
resource compiler) ottengo un file .RES da inserire nel progetto VBP.
Una roba simile a questa:
#define CREATEPROCESS_MANIFEST_RESOURCE_ID    1
#define RT_MANIFEST    24
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "MyProgram.exe.manifest"
Ocio che la dimensione del manifest, in tal caso, deve essere multipla di 4 
bytes.
Bye
Raf 

 />
[..cut..]
Ok, l'ho fatto a mano.
Ho notato una cosa interessante: non ha importanza che l'attributo name 
corrisponda al nome delle exe n� che l'attributo version corrisponda 
all'effettiva versione: funziona comunque. Questa � una buona cosa perch� � 
facile dimenticarsi di aggiornare ad ogni nuova versione anche il manifest.
Per verificare la mia teoria senza incorrere in problemi di caching che ho 
letto potrebbero fuorviare ho ho copiato sempre in nuove cartelle dopo aver 
fatto le modifiche. E funziona.
La cosa che invece non sapevo del manifest e che non mi piace � che se l'UAC 
� mantenuto attivo (come credo sia giusto che sia) viene sempre chiesto ad 
ogni avvio del programma la conferma per avviarlo con i diritti di 
amministratore.
A questo punto, anzich� "imporre" una scelta agli utenti, posso 
semplicemente spiegare loro che possono avviare il programma come 
amministratori cliccando di destro e scegliendo "Esegui come amministratore" 
e che se vogliono possono anche decidere di avviare sempre quel programma 
come amministratore adando in propriet� -> Compatibilit� e selezionando 
"Esegui questo programma come amministratore".
Chiosa finale: ma � mai possibile che bisogna fare tutto questo casino con 
diritti di amministrazione per consentire un TimeSync tra pi� PC in rete ? E 
la modifica dell'ora � solo una cosa con cui mi sono scontrato adesso... 
chiss� quante altre operazioni simili ed (all'apparenza) innocue richiedono 
i diritti...
Ciao, ToSka

 (all'apparenza) innocue richiedono i diritti...
Lo so, ma cosa vuoi farci?
Comunque io ho trovato un'ulteriore soluzione di compromesso (sebbene un po' 
arzigogolata e poco flessibile) che per� evita di usare il manifest o di 
costringere l'utente ad avviare il programma con "run as admin": le 
operazioni che richiedono necessariamente l'esecuzione come admin le confino 
in un secondo exe, che viene lanciato dal programma principale con 
ShellExecuteEx+opportuni parametri (come se l'utente avesse scelto "run as 
admin"), in modo tale che il seccante "elevation prompt" esca fuori solo e 
soltanto quando � strettamente necessario e non ad ogni avvio del programma 
principale.
Magari ti ho dato un nuovo spunto...
Ciao
Raf 


Che un processo giri con privilegi di utenti diversi da quello loggato non ï¿½ 
solo possibile ma anche necessario. P.es. i servizi girano anche quando 
nessun utente ï¿½ loggato e per loro ï¿½ possibile stabilire se essere avviati 
con i privilegi dell'utente SYSTEM o con quelli di uno specifico utente 
(
p.es
. un utente che puï¿½ accedere alla rete etc.).
Come funziona:
1. LogonUser ti permette di eseguire il logon di un utente passando 
username, password e dominio (se necessario). Questo non significa che 
l'utente del logon iniziale cambia: piï¿½ utenti possono essere loggati 
contemporaneamente ma solo uno ï¿½ l'utente che ha aperto il desktop (benchï¿½ 
possano coesistere piï¿½ desktop, ma questo ï¿½ un altro discorso).
2. ImpersonateLoggedOnUser consente di associare il processo in esecuzione 
ad un utente. Passando l'utente loggato con LogonUser ï¿½ possibile associare 
il processo in esecuzone all'utente appena loggato. Di nuovo, questo non 
vuol dire che il desktop assume il nuovo utente: il cambiamento riguarda 
solo il processo corrente (e i children eventuali). A questo punto il 
processo ha i privilegi dell'utente loggato e puï¿½ agire per esso.
3. Per riportare il processo sotto l'utente iniziale ï¿½ sufficiente (e 
consigliabile) chiamare la funzione RevertToSelf.
Naturalmente per poter chiamare LogonUser devi disporre di username e 
password dell'utente che vuoi impersonare. Si pone quindi il problema di 
dove e come custodire queste informazioni. Se non puoi chiederle ad un 
operatore sarebbe bene usare una crittografia valida di queste informazioni. 
Resta il problema di come e quando aggiornare questi dati se vengono 
cambiati dall'amministratore del pc/dominio.
Stefano

 Raf
Come dicevo a ToSka ï¿½ possibile far impersonare qualsiasi utente ad un 
processo, incluso quindi l'amministratore del pc (o un amministratore di 
rete). Naturalmente ï¿½ necessario conoscere username e password dell'utente 
che si deve impersonare.
Ciao,
Stefano 

 (
p.es
. un utente che pu� accedere alla rete etc.).
[..cut..]
Grazie per la dettagliata spiegazione. Con la gestione dei logon la cosa
diventa per� molto pesante.. francamente andare a spiegare agli utenti che
devono inserire un'altra user/password per questa funzionalit� non me la
sento. 

 dell'utente che si deve impersonare.
Eh ma lo so e l'ho sfruttato varie volte, ma in Vista � diverso.
Anche se conosci user e pass, con tutti i problemi che derivano dal doverla 
memorizzare, e usi le api logonuser, impersonateloggedonuser per impersonare 
un utente amministratore (a parte che nell'esempio di ToSka l'utente 
corrente *� gi�* amministratore), comunque non riesci a far girare il 
processo con privilegi elevati _senza interagire con l'utente_.
� un paradigma della sicurezza di Vista.
E, come dicevo poi, non ho ancora trovato un modo per far comparire 
l'elevation prompt durante l'esecuzione di un programma, al momento di 
effettuare un'operazione che richiede appunto i privilegi elevati (e non 
all'avvio) se non spostando l'operazione critica in un exe secondario.
Le uniche vie sono quelle spiegate in questo articolo:
http://msdn.microsoft.com/en-us/library/ms717801.aspx
Bye
Raf 


http://msdn.microsoft.com/en-us/library/ms717801.aspx
Disabilitando l'UAC sul pc i problemi sussitono ancora?
Dico cos� perch� finora in quel modo sono riuscito a risolvere quel tipo di
problemi.
--
ciao
  Stefano

 tipo di problemi.
In pratica, al di l� delle effettive "rogne" introdotte da Vista con l'UAC e 
la virtualization, non mi sognerei mai di abbassare il livello di sicurezza 
del pc di un cliente solo per far girare la mia applicazione (ehm, lo 
ammetto: magari 6-7 anni fa non la pensavo cos�...).
Se poi c'� di mezzo il sistemista di un qualche ente pubblico o grossa 
azienda, figuriamoci come � contento di lasciartelo fare...
Ciao
Raf

azienda, figuriamoci come � contento di lasciartelo fare...
Dal momento che l'applicazione da installare normalmente � una delle pi�
importanti per il pc, finora sono sempre riuscito a farlo.
Per� � interessante sapere che ci sono altre strade, anche se spero di non
doverle mai imboccare.
--
ciao
  Stefano

 doverle mai imboccare.
Per eliminare gli avvisi e le richieste di consenso, da quanto ho capito,
l'unica soluzione � disattivare lo UAC. Altrimenti come minimo per le
operazioni da amministratore (cambio dell'ora) ti becchi il tuo bel popup.

 ï¿½ un paradigma della sicurezza di Vista.
Cioï¿½ vuoi dire che se faccio impersonare un utente ad un processo, Vista 
interviene in qualche modo? Non mi pare. Io ho Vista sul portatile ma accedo 
come admin reale quindi non posso metterci la mano sul fuoco. Perï¿½ se cosï¿½ 
fosse sarebbe impossibile far girare qualsiasi servizio.
Riguardo la memorizzazione: se i dati sono criptati adeguatamente, non mi 
pare un problema cosï¿½ stressante.
D'altra parte in quale altro modo puï¿½ far eseguire al processo un'operazione 
che richiede privilegi superiori a quelli dell'utente loggato? Che io sappia 
solo in tre modi:
(1) facendo impersonare al processo un utente con privilegi adeguati
(2) facendo loggare l'utente con le credenziali di un admin (o altro utente 
autorizzato) - cosa ovviamente deprecabile
(3) cambiando le policy di quell'utente in modo che sia abilitato 
all'operazione (se ï¿½ il cambio dell'ora forse non sarebbe cosï¿½ frammatico 
concederglielo)
Personalmente preferisco la prima soluzione. Spesso la terza consente 
stabilmente all'utente di eseguire operazioni che erano state proibite a 
ragion veduta.
Stefano

 sento.
Come vuoi, perï¿½ non dovrebbero inserire il dato manualmente: dovresti 
memorizzarlo tu da qualche parte (se loro hanno un account da amministratore 
lo potrebbero semplicemente usare per loggarsi e fine dei problemi).
Per me resta la soluzione migliore. In subordine potresti abilitare la 
funzionalitï¿½ (settaggio del clock) per l'utente che si logga tramite le 
policies di sistema, ma questo richiede un intervento sistemistico 
decisamente piï¿½ invasivo.
Stefano

 proibite a ragion veduta.
Sono d'accordo, ma ripeto, in Vista si � vincolati ad interagire con 
l'utente (se UAC � abilitato), prima di poter consentire operazioni che 
richiedono privilegi amministrativi, e questo pu� avvenire solo in questi 
modi:
- con "Run As Admin", che fa apparire la dialog box di richiesta credenziali 
di un admin (se loggati come standard user) o la dialog box di conferma a 
proseguire (elevation prompt) se loggati come admin
- configurando il programma per essere eseguito con privilegi di full admin 
(o col manifest o come spiegato nell'articolo sopra citato), che comporta la 
comparsa di una dialog box all'avvio del programma stesso
A quanto mi � dato sapere, non � invece possibile cambiare "in corsa" il 
livello di integrit� di un processo una volta che � stato avviato, ossia, 
anche se conosci user e pass di admin e usi le api 
logonuser/impersonateloggedonuser, il processo corrente continuer� ad essere 
in esecuzione senza privilegi elevati.
A dire il vero esiste un modo per avviare un processo come admin senza il 
famigerato elevation prompt: farlo eseguire con l'identit� di sistema locale 
(LocalSystem).
In pratica quindi occorre avere un servizio ad hoc che avvii il processo 
dietro richiesta.
Qui c'� un esempio (in C++): 
http://www.codeproject.com/KB/vista-security/VistaSessions.aspx
E qui un altro: 
http://www.codeproject.com/KB/vista-security/SubvertingVistaUAC.aspx
Bye
Raf