1package CyrusSasl; 2 3import javax.security.auth.callback.*; 4import java.io.*; 5 6public class GenericClient extends GenericCommon implements SaslClient 7{ 8 9 private byte[]initial_response; 10 private String mechanism; 11 private boolean hasinitresp; 12 private javax.security.auth.callback.CallbackHandler cbh; 13 14 GenericClient(int cptr, String mechlist, 15 java.util.Hashtable props, 16 javax.security.auth.callback.CallbackHandler cbh) 17 { 18 ptr=cptr; 19 this.cbh = cbh; 20 21 /* set properties */ 22 super.setcommonproperties(props); 23 24 initial_response = jni_sasl_client_start(cptr, mechlist); 25 } 26 27 private native byte[] jni_sasl_client_start(int ptr, 28 String mechlist); 29 30 /** 31 * Perform a step. start() must have been preformed succesfully 32 * before this step() can be called. A client should call this 33 * method until it receives notification from the server that 34 * authentication is complete. Any protocol specific decoding (such 35 * as base64 decoding) must be done before calling step(). The 36 * return byte array should be encoded by the protocol specific 37 * method then sent to the server 38 * 39 * @param challenge byte[] from server (must be protocol specific decode before) 40 * @exception saslException sasl exception 41 * @return the byte[] you should send to the server */ 42 43 public byte[] evaluateChallenge(byte[] challenge) throws SaslException 44 { 45 /* xxx this should check for empty challenge & existing initial 46 sasl challenge */ 47 byte[] out=null; 48 49 if (complete && challenge == null) { 50 /* we're already done and there's no challenge */ 51 return null; 52 } 53 54 if (challenge==null) { 55 out=jni_sasl_client_step(ptr, null, 0); 56 } else { 57 out=jni_sasl_client_step(ptr, challenge, challenge.length); 58 } 59 60 return out; 61 } 62 63 private native byte[] jni_sasl_client_step(int ptr, 64 byte[] in, 65 int inlen); 66 67 68 public boolean hasInitialResponse() 69 { 70 return hasinitresp; 71 } 72 73 /** 74 * Use this method to obtain the name of the mechanism being 75 * negotiated with the server. After giving start() a list of 76 * mechanisms one will be chosen. Use this method to determine which 77 * one if being used if any. 78 * 79 * @return the mechanism currently negotiated or already negotiated */ 80 81 public String getMechanismName() 82 { 83 return mechanism; 84 } 85 86 /* called from C layer */ 87 private void callback_setmechanism(String mech, int initresp) 88 { 89 mechanism = mech; 90 hasinitresp = initresp != 0; 91 } 92 93 private String userid; 94 private String authid; 95 private String password; 96 private String realm; 97 98 private void do_callbacks(int wantuid, int wantaid, int wantpass, int wantrealm) throws SaslException 99 { 100 int numcb = wantuid+wantaid+wantpass+wantrealm; 101 102 Callback[] cbs = new Callback[numcb]; 103 int pos = 0; 104 105 NameCallback nc = null; 106 NameCallback nc2 = null; 107 PasswordCallback pc = null; 108 RealmCallback rc = null; 109 110 if (wantuid==1) { 111 nc = new NameCallback("Please enter your authorization id"); 112 cbs[pos] = nc; 113 pos++; 114 } 115 116 if (wantaid==1) { 117 nc2 = new NameCallback("Please enter your authentication id"); 118 cbs[pos] = nc2; 119 pos++; 120 } 121 122 if (wantpass==1) { 123 pc = new PasswordCallback("Please enter your password", false); 124 cbs[pos] = pc; 125 pos++; 126 } 127 128 if (wantrealm==1) { 129 rc = new RealmCallback("Please enter your realm"); 130 cbs[pos] = rc; 131 pos++; 132 } 133 134 try { 135 cbh.handle(cbs); 136 } catch (UnsupportedCallbackException e) { 137 throw new SaslException("Unsupported callback",null); 138 } catch (IOException e) { 139 throw new SaslException("IO exception",null); 140 } 141 142 if (nc!=null) { 143 this.userid = nc.getName(); 144 } 145 if (nc2!=null) { 146 this.authid = nc2.getName(); 147 } 148 if (pc!=null) { 149 this.password = new String(pc.getPassword()); 150 } 151 if (rc!=null) { 152 this.realm = rc.getRealm(); 153 } 154 } 155 156 private String get_userid(int a) 157 { 158 return userid; 159 } 160 private String get_authid(int a) 161 { 162 return authid; 163 } 164 private String get_password(int a) 165 { 166 return password; 167 } 168 private String get_realm(int a) 169 { 170 return realm; 171 } 172 173 public InputStream getInputStream(InputStream source) throws IOException 174 { 175 if (getSecurity() > 0) { 176 return new SaslInputStream(source,this); 177 } else { 178 // no security layer, no indirection needed 179 return source; 180 } 181 } 182 183 public OutputStream getOutputStream(OutputStream dest) throws IOException 184 { 185 if (getSecurity() > 0) { 186 return new SaslOutputStream(dest,this); 187 } else { 188 // no security layer, no indirection needed 189 return dest; 190 } 191 } 192 193 public byte[] createInitialResponse(){ 194 /* xxx this is deprecated */ 195 return initial_response; 196 } 197} 198