Newsgroup: it.comp.java
Titolo: com.ms.security, com.ms.security.PermissionID.FILEIO ed errore in compazione

Ho bisogno di permettere ad un'applet di leggere e scrivere su HD.
Nessun problema se l'utente ha Java di Sun, che accetta i certificati 
generati con keytool, ma mi sto impazzendo per scrivere una versione 
compatibile con la JVM di Microsoft (sì., d'accordo, è una mondezza, ma è 
l'unica che molti utenti hanno, non tutti hanno voglia e capacità di 
aggiornare la JVM, e insieme a qualcosa tipo "siete vivamente invitati a 
scaricare la versione più aggiornata di java dal seguente link", vorrei 
inserire una seconda versione dell'applet per i più pigri).
Ho trovato, a fatica, "Microsoft SDK for Java 4.0", e con makecert, cert2spc 
e signcode ho provato a firmare l'applet. Apparentemente, tutto a posto 
(signed but not timestamped, non dovrebbe funzionare più quando il 
certificato scade, ma per ora mi basta).
SORPRESA: NON LEGGO E NON SCRIVO DA HD, ESATTAMENTE COME PRIMA... anche 
tutto sembra andato a buon fine.
Cerco un po' in rete, e mi sembra di capire che bisogna aggiungere 
esplicitamente i permessi alla classe com.ms.security.
E QUI VIENE IL MIO PROBLEMA, perchè il mio compilatore più vecchio è java 
1.2 di SUN (che non conosce la classe com.ms.security), e non ho tool 
alternativi per Microsoft. Come posso evitare errori in compilazione?
Il seguente codice:
try
 {
  Class s=Class.forName("com.ms.security.PolicyEngine");
  if (s!=null)
   {s.assertPermission(com.ms.security.PermissionID.FILEIO);}
 }
catch(Throwable e)
 {System.out.println("Error: "+e);}
Dà, in compilazione, l'errore::
    package com.ms.security does not exist
    s.assertPermission(com.ms.security.PermissionID.FILEIO);
Ho ancghe provato modificare con Class p=com.ms.security.PermissionID; e 
s.assertPermission(p.FILEIO);, ma stavolta l'errore è stato "No variable 
FILEIO
defined in class java.lang.Class"
Come posso procedere?
Modificando il codice?
N.B. Non so se può servire, ma nell'elenco dei seguenti comandi presenti in 
C:\Programmi\Microsoft SDK for Java 4.0\Bin, ce n'è uno che potrei usare al 
posto di javac per compilare? Ecco l'elenco
javasign.dll, jps.dll, msjvc.dll, signer.dll
appletviewer.exe, cabarc.exe, cert2spc.exe, certmgr.exe, chkjava.exe, 
ChkTrust.exe, ClassD.exe, ClassR.exe, ClassVue.exe, clspack.exe, 
cprmedit.exe, DUBuild.exe, guidgen.exe, IntegrationClasses.exe, 
IntegrationClasses2000.exe, JActiveX.exe, javah.exe, JAVAREG.EXE, 
javasrc.exe, jexegen.exe, jvc.exe, JView.exe, makecert.exe, makectl.exe, 
msjavah.exe, NMAKE.EXE, PIniEdit.exe, qvue.exe, ResMerge.exe, setreg.exe, 
signcode.exe, Uninstaller.exe, vjreg.exe, WJView.exe
javazone.hlp

 
Se guardi all'interno della directory C:\WINNT\Java\Packages (o
C:\WINDOWS\Java\Packages) trovi alcuni file zippati con nomi assolutamente
casuali... questo è il Runtime Environmenti di Microsoft. Se apri gli zip
uno per uno trovi la stessa struttura dei file .jar (in fondo si tratta
dello stesso formato). Cerca nella struttura di ciascun file la directory
com/ms/security. Quando l'avrai trovata, il file che stai esaminando è da
includere all'interno del classpath del compilatore. In questo modo dovrebbe
portarti dentro le costanti di cui hai bisogno.
Per inciso, puoi compilare per la JVM Microsoft anche con il JDK 1.5, se
passi al compilatore le opzioni
-target 1.1 -source 1.3
-- 
Fermiamo scientology prima che sia troppo tardi!!!
http://xenu.com-it.net
 - 
http://xenu.freewinds.cx/
 - 
http://www.xenu.net/
(per rispondere personalmente leva IlDitoDalCulo)

 casuali... questo č il Runtime Environmenti di Microsoft.
Grazie mille... ho fatto un passo avanti, ma nella sostanza non ho ancora 
risolto. Infatti sono riuscito a compilare con successo
il seguente codice, inserito nel main della classe principale (ho anche 
provato ad inserirlo in tutte le classi che richiedono FileDialog, e piů in 
generale accesso all'input-output):
try
 {
  if (Class.forName("com.ms.security.PolicyEngine")!=null)
   {
    com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.EXEC);
    com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.FILEIO);
    com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.MULTIMEDIA);
    com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.NETIO);
    com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.PRINTING);
    com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.PROPERTY);
    com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.REFLECTION);
    com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.REGISTRY);
    com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.SECURITY);
    com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.SYSSTREAMS);
    com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.SYSTEM);
    com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.THREAD);
    com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.UI);
    com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.USERFILEIO);
    System.out.println("Dovrei aver settato i permessi (???)..."); //Questo 
messaggio viene stampato nella console
   }
 }
catch(Throwable e)
 {System.out.println("Errore: "+e);}
La cosa strana č che, nonostante l'applet sia "signed, but not timestamped" 
(dovrebbe funzionare fino alla scadenza del certificato), e nonostante mi
compaia correttamente la richiesta se voglio eseguire il codice (cosa che 
non succede se la firma dell'applet č assente o non č andata a buon fine), 
continuo
a non riuscire assolutamente a leggere e scrivere su HD. Intercetto sempre 
un'eccezione tipo la seguente:
com.ms.security.SecurityExceptionEx[input/finestra.salvafile]: FileDialog 
creation denied.
 at com/ms/security/permissions/UIPermission.check
 at com/ms/security/PolicyEngine.deepCheck
 at com/ms/security/PolicyEngine.checkPermission
 at com/ms/security/StandardSecurityManager.chk
 at com/ms/security/StandardSecurityManager.checkFileDialog
 at java/awt/FileDialog.<init>
 at input/finestra.salvafile
 at input/finestra.aggiornamento
 at input/finestra.access$40
 at input/finestra$azione.actionPerformed
 at java/awt/Button.processActionEvent
 at java/awt/Button.processEvent
 at java/awt/Component.dispatchEventImpl
 at java/awt/Component.dispatchEvent
 at java/awt/EventDispatchThread.run
Insomma, IL BROWSER MI CHIEDE SE VOGLIO ESEGIRE IL CODICE DI UN  UTENTE NON 
ATTENDIBILE (giusto, non ho un certificato di Verisign o affini), MA POI, 
ANCHE SE ACCETTO, NON FA NULLA DI PIŮ DI UN'APPLET NON FIRMATA. Quale 
sarebbe il vantaggio??? Come cavolo faccio a far sě che l'applet firmata 
legga e scriva da HD????
N.B. La procedura che ho seguito per firmare l'applet č la seguente;
path=C:\Programmi\Microsoft SDK for Java 4.0\Bin
makecert.exe -sv ChiavePrivata.pvk -n "CN=prova" ChiavePubblica.cer
cert2spc ChiavePubblica.cer ChiavePubblica.spc
cabarc -r -p N myapplet.cab [elenco dei files e delle cartelle da inserire 
nel cab]
signcode -j JavaSign.dll -jp High -spc ChiavePubblica.spc -v 
ChiavePrivata.pvk -n "test" -i 
http://www.prova.it/
 myapplet.cab
...e il codice nella pagina htnl č il seguente:
 <APPLET code="prova.class" codebase="[percorso]" name="test" width=1 
height=1>
  <PARAM NAME="cabbase" VALUE=myapplet.cab>
  <PARAM NAME="parametroprivato" VALUE="abc>">
  <PARAM NAME="comeprecedente" VALUE="def"></APPLET>

 legga e scriva da HD????
Ho guardato l'albero delle chiamate, arrivando anche a decompilare il codice
delle classi contenute nel runtime environment della JVM Microsoft. Innanzi
tutto, sembra che non ti sia negato il permesso di scrivere sul disco fisso
(cosa che puoi fare utilizzando tranquillamente java.io.File
java.io.FileOutputStream), ma ti è impedito di aprire una finestra di
dialogo del tipo "Salva con nome".
Seguendo l'albero delle chiamate a partire da java.awt.FileDialog, il codice
del costruttore (decompilato) è questo:
    public FileDialog(Frame frame, String s, int i) {
        super(frame, s, true);
        super.name_count = nameCounter++;
        mode = i;
        SecurityManager securitymanager = System.getSecurityManager();
        if(securitymanager != null && (securitymanager instanceof
StandardSecurityManager))
            ((StandardSecurityManager)securitymanager).checkFileDialog();
        setLayout(null);
    }
In pratica l'oggetto FileDialog ottiene il security manager corrente, e
richiama su di esso il metodo "checkFileDialog". Sempre seguento lo stack
dell'eccezione che hai riportato, sembra che il security manager allocato in
questo caso sia lo StandardSecurityManager. Il codice di checkFileDialog è
questo:
    public void checkFileDialog() {
        chk(new UIAccessRequest(8));
    }
Letteramente viene creato un oggetto di tipo UIAccessRequest e passato al
metodo chk. Non ho idea di cosa significhi il flag "8", fatto sta che è un
valore statico incorporato all'interno del codice... in pratica sembra non
guardare NESSUNA impostazione in nessun file di configurazione. Proseguiamo
nell'albero delle chiamate, prima con il costruttore di UIAccessRequest e
poi con la chiamata a chk:
    public UIAccessRequest(int i) {
        accessType = i;
        needWarning = false;
    }
    private void chk(ISecurityRequest isecurityrequest) {
        try {
            PolicyEngine.checkPermission(isecurityrequest);
            return;
        }
        catch(SecurityException securityexception) {
            securityexception.printStackTrace();
            throw securityexception;
        }
    }
A sua volta chk chiama il metodo statico checkPermisson di PolicyEngine,
passandogli l'oggetto UIAccessRequest creato prima:
    public static void checkPermission(ISecurityRequest isecurityrequest) {
        deepCheck(isecurityrequest.getPermissionID(), isecurityrequest);
    }
e la chiamata passa quindi a deepCheck:
    private static native void deepCheck(PermissionID permissionid, Object
obj);
...metodo nativo, che dal suo interno (vedendo lo stack trace) sembra
richiamare il metodo check di UIPermission passandogli l'oggetto
UIAccessRequest, che abbiamo visto prima costruito con flag "8":
    public void check(Object obj) {
        if(!(obj instanceof UIAccessRequest))
            throw new IllegalArgumentException();
        UIAccessRequest uiaccessrequest = (UIAccessRequest)obj;
        if((flags & 4) == 0)
            uiaccessrequest.needWarning = true;
        if((uiaccessrequest.accessType & flags) == 0) {
            String s;
            if(uiaccessrequest.accessType == 1)
                s = "Clipboard access denied.";
            else
            if(uiaccessrequest.accessType == 2)
                s = "Top-level window creation denied.";
            else
            if(uiaccessrequest.accessType == 8)
                s = "FileDialog creation denied.";
            else
            if(uiaccessrequest.accessType == 16)
                s = "Event queue access denied.";
            else
                s = "Internal Error.  Invalid UIAccessRequest.";
            throw new SecurityExceptionEx(s);
        } else {
            return;
        }
    }
...eh già. Il flag "8" blocca la creazione della finestra di dialogo.
A quanto pare per consentirti la creazione della finestra di dialogo,
deepCheck non deve richiamare check di UIPermission, che di default nega
tutto. Qui non posso aiutarti più di tanto perchè non conosco come la JVM
microsoft stabilisca i permessi... ma da qualche parte nella directory di
sistema (o nel registro) ci deve essere un file di configurazione che forzi
la JVM a restituire un SecurityManager diverso alla chiamata di
System.getSecurityManager() all'inizio.
Faccio ancora un po' di ricerche....


 dialogo del tipo "Salva con nome".
Ti ringrazio infinitamente, mi sembra che tu ne capisca davvero tanto, e non 
sempre riesco a seguirti nei dettagli, ma a naso ho l'impressione che il 
problema non è solo la FileDialog: da un'altra parte, dove molto più 
modestamente cerco di aprire un file ben preciso, la risposta è il seguente 
errore:
com.ms.security.SecurityExceptionEx[output/invio.<init>]: cannot access file 
utente.txt
 at com/ms/security/permissions/FileIOPermission.check
 at com/ms/security/PolicyEngine.deepCheck
 at com/ms/security/PolicyEngine.checkPermission
 at com/ms/security/StandardSecurityManager.chk
 at com/ms/security/StandardSecurityManager.checkRead
 at java/io/FileInputStream.<init>
 at java/io/FileReader.<init>
 at output/invio.<init>
 at input/finestra.aggiornamento
 at input/finestra.access$40
 at input/finestra$azione.actionPerformed
 at java/awt/Button.processActionEvent
 at java/awt/Button.processEvent
 at java/awt/Component.dispatchEventImpl
 at java/awt/Component.dispatchEvent
 at java/awt/EventDispatchThread.run
Ho proprio l'impressione che la firma dell'applet sia inefficace, ma non so 
perchè.
A questo punto inizierei con alcuni punti fermi, almeno per poter escludere 
alcune cause:
1) La procedura corrente è corretta? Ed è corretto il programma che uso 
(Microsoft SDK for Java 4.0)?
path=C:\Programmi\Microsoft SDK for Java 4.0\Bin
makecert.exe -sv ChiavePrivata.pvk -n "CN=prova" ChiavePubblica.cer
cert2spc ChiavePubblica.cer ChiavePubblica.spc
cabarc -r -p N myapplet.cab [elenco dei files e delle cartelle da inserire 
nel cab]
signcode -j JavaSign.dll -jp High -spc ChiavePubblica.spc -v 
ChiavePrivata.pvk -n "test" -i 
http://www.prova.it/
 myapplet.cab
2) Il manifest.mf, se uso la procedura per la firma di SUN, vine riempito 
con gli SHA1 dei files; con signcode nulla di tutto questo avviene... manca 
qualcosa, o è giusto così (magari, viene scritto qualcosa nell'archivio in 
un formato Microsoft, e non in un singolo file)?
3) Perchè i permessi siano assegnati, dovrebbe bastare la firma, come al 
punto 1, o è necessario anche aggiungere righe come la seguente:
try
 {
  if (Class.forName("com.ms.security.PolicyEngine")!=null)
   {
    com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.NETIO);
    //ecc. ecc.
   }
 }
catch(Throwable e)
 {System.out.println("Errore: "+e);}
4) Se le righe precedenti vanno aggiunte, DOVE occorre farlo? Nel main della 
classe principale del jar (anzi, del CAB), nel costruttore di tutte le 
classi che usano input-output, o nel metodo che accede all'HD, appena prima 
di aprire il file? E nel caso vengano usati, per l'input-output, metodi 
statici di un'altra classe, dove inserire tali permessi? O sarebbe un 
problema?
5) Oltre ai seguenti campi che ho trovato in rete in un file (credo fosse il 
sorgente di un programma per la dichiarazione dei redditi Unico 98), ne 
esistono altri? Quali dovrei, eventualmente, settare, e quali sarebbero 
inutili? Diciamo per: leggere e scrivere su HD (fileDialog compresi), 
attivare una connessione protetta (SSL) e, forse (non sono sicuro, forse la 
libreria di iText simula in qualche modo anche la stampa.
EXEC, FILEIO, MULTIMEDIA, NETIO, PRINTING, PROPERTY, REFLECTION, REGISTRY, 
SECURITY, SYSSTREAMS, SYSTEM, THREAD, UI, USERFILEIO

 Microsoft
Per fare chiarezza, e cercare di escludere almeno alcune cause di errore, ho 
creato il seguente file java:
------------------------------------------------------------------------------------------
import java.applet.*;
import java.io.*;
public class prova extends Applet
 {
  public void init()
   {
    try
     {
      if (Class.forName("com.ms.security.PolicyEngine")!=null)
       {
        com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.CLIENTSTORE);
        com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.EXEC);
        com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.FILEIO);
        com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.MULTIMEDIA);
        com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.NETIO);
        com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.PRINTING);
        com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.PROPERTY);
        com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.REFLECTION);
        com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.REGISTRY);
        com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.SECURITY);
        com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.SYSSTREAMS);
        com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.SYSTEM);
        com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.THREAD);
        com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.UI);
        com.ms.security.PolicyEngine.assertPermission(com.ms.security.PermissionID.USERFILEIO);
        System.out.println("Dovrei aver settato i permessi (???)...");
       }
     }
    catch(Throwable e)
     {System.out.println("Errore: "+e);}
    System.out.println("Versione java: "+System.getProperty("java.vendor")+" 
"+System.getProperty("java.version"));
    System.out.println("Sistema operativo: "+System.getProperty("
os.name
"));
    try
     {
      BufferedReader file=new BufferedReader(new FileReader("prova.txt"));
      String s=file.readLine();
      System.out.println(s);
      file.close();
     }
    catch (Exception e) {System.out.println("Errore: "+e);}
   }
 }
------------------------------------------------------------------------------------------
Poi ho creato, e firmato con i certificati già creati in precedenza, il file 
cab con il seguente file batch:
------------------------------------------------------------------------------------------
D:
cd [path corretto]
C:\jdk1.2.1\bin\javac prova.java
echo Manifest-Version: 1.0>META-INF\MANIFEST.MF
echo Created-By: 1.2.1 (Sun Microsystems Inc.)>>META-INF\MANIFEST.MF
echo Main-Class: equazioni>>META-INF\MANIFEST.MF
path=C:\Programmi\Microsoft SDK for Java 4.0\Bin
cabarc -r -p N prova.cab prova.class META-INF\MANIFEST.MF
del *.class META-INF\MANIFEST.MF
signcode -j JavaSign.dll -jp High -spc ChiavePubblica.spc -v 
ChiavePrivata.pvk -n "prova" -i 
http://www.prova.it/
 prova.cab
------------------------------------------------------------------------------------------
Infine ho creato il seguente ifile html:
------------------------------------------------------------------------------------------
<HTML>
<HEAD>
<TITLE>Applet</TITLE>
</HEAD>
<BODY TEXT="#000000" LINK="#0000FF" VLINK="#800080">
<FONT FACE="arial" SIZE=4 COLOR="#000000"><P ALIGN=center>
<APPLET code="prova.class" width=1 height=1>'
<PARAM NAME="cabbase" VALUE="prova.cab"></APPLET>
</BODY>
</HTML>
------------------------------------------------------------------------------------------
Il risultato è stato il seguente:
------------------------------------------------------------------------------------------
Microsoft (R) VM for Java, 5.0 Release 5.0.0.3810
==============================================
?  guida
c  cancella
f  finalizzazione
g  raccolta scarti
m  utilizzo memoria
q  esci
t  elenco thread
==============================================
Dovrei aver settato i permessi (???)...
Versione java: Microsoft Corp. 1.1.4
Sistema operativo: Windows NT
com.ms.security.SecurityExceptionEx[prova.init]: cannot access file 
prova.txt
 at com/ms/security/permissions/FileIOPermission.check
 at com/ms/security/PolicyEngine.deepCheck
 at com/ms/security/PolicyEngine.checkPermission
 at com/ms/security/StandardSecurityManager.chk
 at com/ms/security/StandardSecurityManager.checkRead
 at java/io/FileInputStream.<init>
 at java/io/FileReader.<init>
 at prova.init
 at com/ms/applet/AppletPanel.securedCall0
 at com/ms/applet/AppletPanel.securedCall
 at com/ms/applet/AppletPanel.processSentEvent
 at com/ms/applet/AppletPanel.processSentEvent
 at com/ms/applet/AppletPanel.run
 at java/lang/Thread.run
Errore: com.ms.security.SecurityExceptionEx[prova.init]: cannot access file 
prova.txt
------------------------------------------------------------------------------------------
Ma sarà adatta Microsoft SDK for Java 4.0 a firmare applet java? Io non sono 
riuscito a trovare tools alterativi (Microsoft ha tolto il supporto a java, 
e rimosso tutti i files per il download...)

 java, e rimosso tutti i files per il download...)
Oltre a Microsoft SDK for Java 4.0 (che era già completo) ho provato ora 
altri due tools the avevo trovato con il P2P, a cui mancava l'essenziale 
javasign.dll, che ho scaricato dal seguente indirizzo: 
http://www.webzila.com/?wz=dll#results
. Risultato: sempre, immancabilmente, 
lo stesso! Non sembra un problema del tool... ma allora, dove sbaglio?