1/* javasasl.c--Java SASL JNI implementation
2 * Tim Martin
3 */
4/***********************************************************
5        Copyright 1998 by Carnegie Mellon University
6
7                      All Rights Reserved
8
9Permission to use, copy, modify, and distribute this software and its
10documentation for any purpose and without fee is hereby granted,
11provided that the above copyright notice appear in all copies and that
12both that copyright notice and this permission notice appear in
13supporting documentation, and that the name of Carnegie Mellon
14University not be used in advertising or publicity pertaining to
15distribution of the software without specific, written prior
16permission.
17
18CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
19THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
20FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR
21ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
23ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
24OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25******************************************************************/
26
27#include <config.h>
28#include <stdio.h>
29#include <sasl.h>
30#include <saslutil.h>
31#include <saslplug.h>
32#include <netdb.h>
33#include <sys/types.h>
34#include <sys/socket.h>
35#include <netinet/in.h>
36#include <assert.h>
37
38#include "javasasl.h"
39
40#define VL(x) /* printf x */
41
42static JNIEnv *globalenv;
43static jobject globalobj;
44
45static int setcomplete(JNIEnv *env, jobject obj);
46
47static void throwexception(JNIEnv *env, int error)
48{
49  jclass newExcCls;
50
51  VL (("Throwing exception!\n"));
52
53  newExcCls = (*env)->FindClass(env, "CyrusSasl/SaslException");
54
55  if (newExcCls == 0) {
56    return;
57  }
58
59  (*env)->ThrowNew(env, newExcCls, sasl_errstring(error,NULL,NULL));
60}
61
62/* server init */
63
64JNIEXPORT jint JNICALL Java_CyrusSasl_ServerFactory_jni_1sasl_1server_1init
65  (JNIEnv *env,
66   jobject obj __attribute__((unused)),
67   jstring jstr)
68{
69  /* Obtain a C-copy of the Java string */
70  const char *str = (*env)->GetStringUTFChars(env, jstr, 0);
71  int result;
72
73  result=sasl_server_init(NULL,str);
74  if (result!=SASL_OK)
75    throwexception(env,result);
76
77  /* Now we are done with str */
78  (*env)->ReleaseStringUTFChars(env, jstr, str);
79
80  return result;
81}
82
83static int
84log(void *context __attribute__((unused)),
85    int priority,
86    const char *message)
87{
88  const char *label;
89  jstring jlabel, jmessage;
90  jclass cls;
91  jmethodID mid;
92
93  if (! message)
94    return SASL_BADPARAM;
95
96  switch (priority) {
97  case SASL_LOG_ERR:
98    label = "Error";
99    break;
100  case SASL_LOG_WARN:
101    label = "Warning";
102    break;
103  case SASL_LOG_NOTE:
104    label = "Note";
105    break;
106  case SASL_LOG_FAIL:
107    label = "Fail";
108    break;
109  case SASL_LOG_PASS:
110    label = "Pass";
111    break;
112  case SASL_LOG_TRACE:
113    label = "Trace";
114    break;
115  case SASL_LOG_DEBUG:
116    label = "Debug";
117    break;
118  default:
119    return SASL_BADPARAM;
120  }
121
122  VL(("I have message %s\n",message));
123  VL(("Trying to call log callback\n"));
124  cls = (*globalenv)->GetObjectClass(globalenv, globalobj);
125  mid = (*globalenv)->GetMethodID(globalenv, cls, "callback_log",
126				  "(Ljava/lang/String;Ljava/lang/String;)V");
127  if (mid == 0) {
128    return SASL_FAIL;
129  }
130
131  /* make label into a java string */
132  jlabel= (*globalenv)->NewStringUTF(globalenv,label);
133
134  /* make message into a java string */
135  jmessage= (*globalenv)->NewStringUTF(globalenv,message);
136
137  /* call java */
138  (*globalenv)->CallVoidMethod(globalenv, globalobj, mid,
139			       jlabel, jmessage);
140
141  /* Now we are done with jlabel */
142  (*globalenv)->ReleaseStringUTFChars(globalenv, jlabel, label);
143
144  /* Now we are done with jmessage */
145  (*globalenv)->ReleaseStringUTFChars(globalenv, jmessage, message);
146
147  VL(("done with log callback"));
148
149  return SASL_OK;
150}
151
152static sasl_callback_t callbacks[] = {
153  {
154    SASL_CB_LOG,      &log, NULL
155  }, {
156    SASL_CB_PASS,     NULL, NULL
157  }, {
158    SASL_CB_USER,     NULL, NULL /* we'll handle these ourselves */
159  }, {
160    SASL_CB_AUTHNAME, NULL, NULL /* we'll handle these ourselves */
161  }, {
162      /* TODO
163	 SASL_CB_ECHOPROMPT, &prompt, NULL
164  }, {
165    SASL_CB_NOECHOPROMPT, &prompt, NULL
166    }, { */
167    SASL_CB_LIST_END, NULL, NULL
168  }
169};
170
171/* client init */
172JNIEXPORT jint JNICALL Java_CyrusSasl_ClientFactory_jni_1sasl_1client_1init
173  (JNIEnv *env,
174   jobject obj __attribute__((unused)),
175   jstring jstr)
176{
177  /* Obtain a C-copy of the Java string */
178  const char *str = (*env)->GetStringUTFChars(env, jstr, 0);
179  int result;
180
181  VL(("client initing\n"));
182
183  result=sasl_client_init(callbacks);
184  if (result!=SASL_OK)
185    throwexception(env,result);
186
187  /* Now we are done with str */
188  (*env)->ReleaseStringUTFChars(env, jstr, str);
189
190  return result;
191}
192
193/* server new */
194
195JNIEXPORT jint JNICALL Java_CyrusSasl_ServerFactory_jni_1sasl_1server_1new
196  (JNIEnv *env,
197   jobject obj __attribute__((unused)),
198   jstring jservice,
199   jstring jlocal,
200   jint jsecflags)
201{
202  sasl_conn_t *conn;
203
204  const char *service = (*env)->GetStringUTFChars(env, jservice, 0);
205  const char *local_domain = (*env)->GetStringUTFChars(env, jlocal, 0);
206  const char *user_domain = NULL;
207  int result;
208
209  if (local_domain) {
210      VL(("local domain = %s\n",local_domain));
211  }
212  if (user_domain) {
213      VL(("user domain = %s\n",user_domain));
214  }
215
216  result=sasl_server_new(service, local_domain, user_domain,
217			 NULL, NULL, NULL, jsecflags, &conn);
218  if (result!=SASL_OK)
219    throwexception(env,result);
220
221  /* Now we are done with str */
222  (*env)->ReleaseStringUTFChars(env, jservice, service);
223  (*env)->ReleaseStringUTFChars(env, jlocal, local_domain);
224
225  return (jint) conn;
226}
227
228
229JNIEXPORT jint JNICALL JNICALL Java_CyrusSasl_ClientFactory_jni_1sasl_1client_1new
230  (JNIEnv *env,
231   jobject obj __attribute__((unused)),
232   jstring jservice, jstring jserver, jint jsecflags, jboolean successdata)
233{
234  sasl_conn_t *conn;
235
236  const char *service = (*env)->GetStringUTFChars(env, jservice, 0);
237  const char *serverFQDN = (*env)->GetStringUTFChars(env, jserver, 0);
238  int result;
239
240  result=sasl_client_new(service, serverFQDN, NULL, NULL, NULL,
241			 jsecflags | (successdata ? SASL_SUCCESS_DATA : 0),
242                         &conn);
243
244  if (result!=SASL_OK)
245    throwexception(env,result);
246
247  /* Now we are done with str */
248  (*env)->ReleaseStringUTFChars(env, jservice, service);
249  (*env)->ReleaseStringUTFChars(env, jserver, serverFQDN);
250
251  return (jint) conn;
252}
253
254/* server start */
255
256JNIEXPORT jbyteArray JNICALL Java_CyrusSasl_GenericServer_jni_1sasl_1server_1start
257  (JNIEnv *env,
258   jobject obj __attribute__((unused)),
259   jint ptr, jstring jstr, jbyteArray jarr, jint jlen)
260{
261  sasl_conn_t *conn;
262  const char *mech = (*env)->GetStringUTFChars(env, jstr, 0);
263  const char *out;
264  unsigned int outlen;
265   int result;
266  jbyteArray arr;
267  char *tmp;
268  char *in=NULL;
269
270  VL(("in server start\n"));
271
272  if (jarr!=NULL)
273    in = (*env)->GetByteArrayElements(env, jarr, 0);
274
275  conn=(sasl_conn_t *) ptr;
276
277  result=sasl_server_start(conn, mech,
278			   (const char *) in, jlen,
279			   &out, &outlen);
280
281  if ((result!=SASL_OK) && (result!=SASL_CONTINUE))
282  {
283
284    throwexception(env,result);
285    return NULL;
286  }
287
288  /* Because SASLv2 does not allow for persistance, we'll copy
289   * it here */
290  tmp = malloc(outlen);
291  if(!tmp) {
292      throwexception(env, SASL_NOMEM);
293      return NULL;
294  }
295
296  memcpy(tmp, out, outlen);
297
298  arr=(*env)->NewByteArray(env,outlen);
299  (*env)->SetByteArrayRegion(env,arr, 0, outlen, (char *)tmp);
300
301  return arr;
302}
303
304
305static int getvalue(JNIEnv *env, jobject obj, char *funcname, char **result, int *len)
306{
307    jclass cls;
308    jmethodID mid;
309    const char *str;
310    jstring jstr;
311
312    /* set up for java callback */
313    cls = (*env)->GetObjectClass(env, obj);
314    mid = (*env)->GetMethodID(env, cls, funcname,
315				  "(I)Ljava/lang/String;");
316    if (mid == 0) {
317	VL(("Can't find %s callback!!!\n",funcname));
318	return SASL_FAIL;
319    }
320
321    VL(("do the callback\n"));
322    jstr = (jstring) (*env)->CallObjectMethod(env, obj, mid);
323
324    if (jstr) {
325        VL(("convert the result string into a char *\n"));
326        str = (*env)->GetStringUTFChars(env, jstr, 0);
327
328        /* copy password into the result */
329        *result=(char *) malloc( strlen(str));
330        strcpy(*result, str);
331        *len=strlen(str);
332
333        /* Now we are done with str */
334        (*env)->ReleaseStringUTFChars(env, jstr, str);
335    } else {
336        *result = NULL;
337        *len = 0;
338    }
339
340    return SASL_OK;
341}
342
343static int callall_callbacks(JNIEnv *env, jobject obj,
344			     int calluid,int callaid,
345			     int callpass,int callrealm)
346{
347    jclass cls;
348    jmethodID mid;
349
350    /* set up for java callback */
351    cls = (*env)->GetObjectClass(env, obj);
352    mid = (*env)->GetMethodID(env, cls, "do_callbacks", "(IIII)V");
353    if (mid == 0) {
354	VL(("Can't find do_callbacks callback!!!\n"));
355	return SASL_FAIL;
356    }
357
358    /* do the callback */
359    (*env)->CallVoidMethod(env, obj, mid,calluid,callaid,callpass,callrealm);
360
361    VL(("callall_callbacks worked\n"));
362    return SASL_OK;
363}
364
365/*
366 * Fills in all the prompts by doing callbacks to java
367 * returns SASL_INTERACT on sucess
368 */
369
370static int fillin_interactions(JNIEnv *env, jobject obj,
371				sasl_interact_t *tlist)
372{
373  sasl_interact_t *ptr=tlist;
374  sasl_interact_t *uid=NULL; int is_uid = 0;
375  sasl_interact_t *aid=NULL; int is_aid = 0;
376  sasl_interact_t *pass=NULL;int is_pass = 0;
377  sasl_interact_t *realm=NULL; int is_realm = 0;
378
379  /* First go through the prompt list to see what we have */
380  while (ptr->id!=SASL_CB_LIST_END)
381  {
382    if (ptr->id==SASL_CB_PASS)
383	{  pass=ptr; is_pass = 1; }
384    if (ptr->id==SASL_CB_AUTHNAME)
385	{ aid=ptr; is_aid = 1; }
386    if (ptr->id==SASL_CB_USER)
387	{ uid=ptr; is_uid = 1; }
388    if (ptr->id==SASL_CB_GETREALM)
389	{ realm = ptr; is_realm = 1; }
390    ptr->result=NULL;
391
392    /* increment to next sasl_interact_t */
393    ptr++;
394  }
395
396  callall_callbacks(env,obj,is_uid,is_aid,is_pass,is_realm);
397
398  if (is_pass) {
399      VL(("in is_pass\n"));
400
401      getvalue(env,obj,"get_password",(char **) &(pass->result),(int *) &(pass->len));
402  }
403  if (is_aid) {
404      VL(("in is_aid\n"));
405
406      getvalue(env,obj,"get_authid",(char **) &(aid->result),(int *) &(aid->len));
407  }
408  if (is_uid) {
409      VL(("in is_uid\n"));
410
411      getvalue(env,obj,"get_userid",(char **) &(uid->result),(int *) &(uid->len));
412  }
413  if (is_realm) {
414      VL(("in is_realm\n"));
415
416      getvalue(env,obj,"get_realm",(char **) &(realm->result),(int *) &(realm->len));
417  }
418
419  /* everything should now be filled in (i think) */
420  VL(("everything should now be filled in (i think)\n"));
421
422  return SASL_INTERACT;
423}
424
425/* client start */
426
427JNIEXPORT jbyteArray JNICALL Java_CyrusSasl_GenericClient_jni_1sasl_1client_1start(JNIEnv *env, jobject obj, jint ptr, jstring jstr)
428{
429  sasl_conn_t *conn=(sasl_conn_t *) ptr;
430  const char *mechlist = (*env)->GetStringUTFChars(env, jstr, 0);
431  const char *out;
432  unsigned int outlen=0;
433  const char *mechusing;
434  int result;
435  sasl_interact_t *client_interact=NULL;
436  char *tmp;
437  jbyteArray arr;
438  jstring jmechusing;
439  jclass cls;
440  jmethodID mid;
441
442  VL(("sasl_start"));
443
444  do {
445
446      result=sasl_client_start(conn, mechlist,
447			       &client_interact,
448			       &out,
449                               &outlen,
450			       &mechusing);
451
452      if (result==SASL_INTERACT) {
453	  int res2 = fillin_interactions(env,obj,client_interact);
454      }
455
456  } while (result==SASL_INTERACT);
457
458  /* ok release mechlist */
459  (*env)->ReleaseStringUTFChars(env, jstr, mechlist);
460
461  if ((result!=SASL_OK) && (result!=SASL_CONTINUE))
462  {
463    throwexception(env,result);
464    return NULL;
465  }
466
467  /* tell the java layer what mechanism we're using */
468
469  /* set up for java callback */
470  cls = (*env)->GetObjectClass(env, obj);
471  mid = (*env)->GetMethodID(env, cls, "callback_setmechanism",
472			    "(Ljava/lang/String;I)V");
473  if (mid == 0) {
474      throwexception(env,SASL_FAIL);
475    return NULL;
476  }
477
478  VL(("mechusing=%s\n",mechusing));
479
480  /* make into mech */
481  jmechusing= (*env)->NewStringUTF(env,mechusing);
482
483  /* do the callback */
484  (*env)->CallVoidMethod(env, obj, mid,jmechusing);
485
486  /* Because SASLv2 does not allow for persistance, we'll copy
487   * it here */
488  tmp = malloc(outlen);
489  if(!tmp) {
490      throwexception(env, SASL_NOMEM);
491      return NULL;
492  }
493
494  memcpy(tmp, out, outlen);
495
496  arr=(*env)->NewByteArray(env,outlen);
497  (*env)->SetByteArrayRegion(env,arr, 0, outlen, (char *)tmp);
498
499  return arr;
500}
501
502/* server step */
503
504JNIEXPORT jbyteArray JNICALL Java_CyrusSasl_GenericServer_jni_1sasl_1server_1step
505
506  (JNIEnv *env,
507   jobject obj __attribute__((unused)),
508   jint ptr, jbyteArray jarr, jint jlen)
509{
510  sasl_conn_t *conn=(sasl_conn_t *) ptr;
511  int result;
512  const char *out;
513  unsigned int outlen;
514  jbyteArray arr;
515  char *in = NULL;
516  char *tmp;
517
518  if (jlen > 0)
519      in = (*env)->GetByteArrayElements(env, jarr, 0);
520
521  result=sasl_server_step(conn, (const char *) in, jlen,
522			  &out, &outlen);
523
524  if ((result!=SASL_OK) && (result!=SASL_CONTINUE))
525  {
526      VL (("Throwing exception! %d\n",result));
527      /* throw exception */
528      throwexception(env,result);
529      return NULL;
530  }
531
532  if (result == SASL_OK) {
533      setcomplete(env,obj);
534  }
535
536  if (jlen > 0)
537      (*env)->ReleaseByteArrayElements(env, jarr,in ,0);
538
539  /* Because SASLv2 does not allow for persistance, we'll copy
540   * it here */
541  tmp = malloc(outlen);
542  if(!tmp) {
543      throwexception(env, SASL_NOMEM);
544      return NULL;
545  }
546
547  memcpy(tmp, out, outlen);
548
549  arr=(*env)->NewByteArray(env,outlen);
550  (*env)->SetByteArrayRegion(env,arr, 0, outlen, (char *)tmp);
551
552  return arr;
553}
554
555
556/*
557 * Tell client we're done
558 */
559static int setcomplete(JNIEnv *env, jobject obj)
560{
561    jclass cls;
562    jmethodID mid;
563
564    VL (("Complete!\n"));
565
566    /* set up for java callback */
567    cls = (*env)->GetObjectClass(env, obj);
568    mid = (*env)->GetMethodID(env, cls, "setcomplete",
569				  "(I)V");
570    if (mid == 0) {
571	VL(("Can't find do_callbacks callback!!!\n"));
572	return SASL_FAIL;
573    }
574
575    /* do the callback */
576    (*env)->CallVoidMethod(env, obj, mid, 5);
577
578    return SASL_OK;
579}
580
581/* client step */
582
583JNIEXPORT jbyteArray JNICALL Java_CyrusSasl_GenericClient_jni_1sasl_1client_1step
584    (JNIEnv *env, jobject obj, jint ptr, jbyteArray jarr, jint jlen)
585{
586  sasl_conn_t *conn=(sasl_conn_t *) ptr;
587  /*  const char *in = (*env)->GetStringUTFChars(env, jstr, 0);*/
588  int result;
589  sasl_interact_t *client_interact=NULL;
590  const char *out;
591  unsigned int outlen;
592  jbyteArray arr;
593  char *in;
594  char *tmp;
595
596  VL(("in client step\n"));
597
598  if (jarr) {
599      in = (*env)->GetByteArrayElements(env, jarr, 0);
600      in[jlen]=0;
601  } else {
602      assert(jlen == 0);
603       in = NULL;
604  }
605
606  VL(("in client step 2\n"));
607
608  globalenv=env;
609  globalobj=obj;
610
611  do {
612      result=sasl_client_step(conn, (const char *) in, jlen,
613			      &client_interact,
614			      &out, &outlen);
615
616      VL(("in client step 3\n"));
617
618      if (result==SASL_INTERACT) {
619	  result = fillin_interactions(env,obj,client_interact);
620      }
621  } while (result==SASL_INTERACT);
622
623  if ((result!=SASL_OK) && (result!=SASL_CONTINUE)) {
624      /* throw exception */
625      VL (("Throwing exception %d\n",result));
626      throwexception(env,result);
627      return NULL;
628  }
629
630  if (result == SASL_OK) {
631      VL (("Setting complete\n"));
632      setcomplete(env,obj);
633  }
634
635  if (jarr) {
636      VL(("about to releasebytearrayelements\n"));
637      (*env)->ReleaseByteArrayElements(env, jarr,in ,0);
638  }
639
640  /* Because SASLv2 does not allow for persistance, we'll copy
641   * it here */
642  tmp = malloc(outlen);
643  if(!tmp) {
644      throwexception(env, SASL_NOMEM);
645      return NULL;
646  }
647
648  VL(("in client step 4\n"));
649
650  memcpy(tmp, out, outlen);
651
652  arr=(*env)->NewByteArray(env,outlen);
653  (*env)->SetByteArrayRegion(env,arr, 0, outlen, (char *)tmp);
654
655  VL(("returning arr\n"));
656  return arr;
657}
658
659
660JNIEXPORT void JNICALL Java_CyrusSasl_GenericCommon_jni_1sasl_1set_1prop_1string
661  (JNIEnv *env,
662   jobject obj __attribute__((unused)),
663   jint ptr, jint propnum, jstring val)
664{
665  sasl_conn_t *conn=(sasl_conn_t *) ptr;
666  const char *value = (*env)->GetStringUTFChars(env, val, 0);
667
668  int result=sasl_setprop(conn, propnum, value);
669
670  if (result!=SASL_OK)
671    throwexception(env,result);
672}
673
674
675JNIEXPORT void JNICALL Java_CyrusSasl_GenericCommon_jni_1sasl_1set_1prop_1int
676  (JNIEnv *env,
677   jobject obj __attribute__((unused)),
678   jint ptr, jint propnum, jint jval)
679{
680
681  sasl_conn_t *conn=(sasl_conn_t *) ptr;
682  int value=jval;
683  int result;
684
685  VL(("sasl conn = %d\n",conn));
686  VL (("propnum = %d\n",propnum));
687
688  result=sasl_setprop(conn, propnum, &value);
689
690  VL (("setprop returned %d\n",result));
691
692  if (result!=SASL_OK)
693    throwexception(env,result);
694}
695JNIEXPORT void JNICALL Java_CyrusSasl_GenericCommon_jni_1sasl_1set_1prop_1bytes
696  (JNIEnv *env,
697   jobject obj __attribute__((unused)),
698   jint ptr, jint propnum, jbyteArray jarr)
699{
700  char *value = (*env)->GetByteArrayElements(env, jarr, 0);
701  sasl_conn_t *conn=(sasl_conn_t *) ptr;
702  int result;
703
704  result=sasl_setprop(conn, propnum, value);
705  if (result!=SASL_OK)
706    throwexception(env,result);
707
708}
709
710/* encode */
711JNIEXPORT jbyteArray JNICALL Java_CyrusSasl_GenericCommon_jni_1sasl_1encode
712  (JNIEnv *env,
713   jobject obj __attribute__((unused)),
714   jint ptr,
715   jbyteArray jarr, jint jlen)
716{
717  sasl_conn_t *conn=(sasl_conn_t *) ptr;
718  char *in = (*env)->GetByteArrayElements(env, jarr, 0);
719  const char *out;
720  unsigned int outlen;
721  char *tmp;
722  int result;
723  jbyteArray arr;
724
725  result=sasl_encode(conn,(const char *) in, jlen, &out, &outlen);
726  if (result!=SASL_OK)
727    throwexception(env,result);
728
729  /* Because SASLv2 does not allow for persistance, we'll copy
730   * it here */
731  tmp = malloc(outlen);
732  if(!tmp) {
733      throwexception(env, SASL_NOMEM);
734      return NULL;
735  }
736
737  memcpy(tmp, out, outlen);
738
739  arr=(*env)->NewByteArray(env,outlen);
740  (*env)->SetByteArrayRegion(env,arr, 0, outlen, (char *)tmp);
741
742  return arr;
743}
744
745/* decode */
746JNIEXPORT jbyteArray JNICALL Java_CyrusSasl_GenericCommon_jni_1sasl_1decode
747  (JNIEnv *env,
748   jobject obj __attribute__((unused)),
749   jint ptr, jbyteArray jarr, jint jlen)
750{
751
752  sasl_conn_t *conn=(sasl_conn_t *) ptr;
753  char *in = (*env)->GetByteArrayElements(env, jarr, 0);
754  const char *out;
755  unsigned int outlen=9;
756  char *tmp;
757  int inlen=jlen;
758  int result;
759  jbyteArray arr;
760
761  result=sasl_decode(conn, (const char *) in, inlen, &out, &outlen);
762  if (result!=SASL_OK)
763    throwexception(env,result);
764
765
766  /* Because SASLv2 does not allow for persistance, we'll copy
767   * it here */
768  tmp = malloc(outlen);
769  if(!tmp) {
770      throwexception(env, SASL_NOMEM);
771      return NULL;
772  }
773
774  memcpy(tmp, out, outlen);
775
776  arr=(*env)->NewByteArray(env,outlen);
777  (*env)->SetByteArrayRegion(env,arr, 0, outlen, (char *)tmp);
778
779  (*env)->ReleaseByteArrayElements(env, jarr, in,0);
780
781  return arr;
782
783}
784
785/*JNIEXPORT jbyteArray JNICALL Java_sasl_saslServerConn_jni_1sasl_1server_1decode
786  (JNIEnv *env, jobject obj, jint ptr, jbyteArray in, jint inlen)
787{
788  return Java_sasl_saslClientConn_jni_1sasl_1client_1decode(env,obj,ptr,in,inlen);
789  }*/
790
791JNIEXPORT void JNICALL Java_CyrusSasl_CommonConn_jni_1sasl_1dispose
792  (JNIEnv *env __attribute__((unused)),
793   jobject obj __attribute__((unused)),
794   jint ptr)
795{
796  sasl_conn_t *conn=(sasl_conn_t *) ptr;
797
798  sasl_dispose(&conn);
799
800}
801
802JNIEXPORT jstring JNICALL Java_CyrusSasl_ServerFactory_jni_1sasl_1server_1getlist
803  (JNIEnv *env,
804   jobject obj __attribute__((unused)),
805   jint ptr, jstring jpre, jstring jsep, jstring jsuf)
806{
807  sasl_conn_t *conn=(sasl_conn_t *) ptr;
808  const char *pre = (*env)->GetStringUTFChars(env, jpre, 0);
809  const char *sep = (*env)->GetStringUTFChars(env, jsep, 0);
810  const char *suf = (*env)->GetStringUTFChars(env, jsuf, 0);
811  const char *list;
812  unsigned int plen;
813  jstring ret;
814
815  int result=sasl_listmech(conn, NULL, pre, sep, suf, &list, &plen, NULL);
816
817  if (result!=SASL_OK)
818  {
819    throwexception(env,result);
820    return NULL;
821  }
822
823  ret= (*env)->NewStringUTF(env,list);
824  if (ret==NULL)
825    throwexception(env, -1);
826
827  return ret;
828}
829
830JNIEXPORT void JNICALL Java_CyrusSasl_GenericCommon_jni_1sasl_1set_1server
831  (JNIEnv *env,
832   jobject obj __attribute__((unused)),
833   jint ptr, jbyteArray jarr, jint jport)
834{
835  sasl_conn_t *conn=(sasl_conn_t *) ptr;
836  unsigned char *ip = (*env)->GetByteArrayElements(env, jarr, 0);
837  char out[52];
838  int result;
839
840  sprintf(out, "%d.%d.%d.%d;%d", ip[0], ip[1], ip[2], ip[3], (int)jport);
841
842  result=sasl_setprop(conn, SASL_IPREMOTEPORT, out);
843
844  VL(("Set IP_REMOTE: %s: %d\n",out, result));
845
846  /* if not set throw an exception */
847  if (result!=SASL_OK)
848    throwexception(env,result);
849}
850
851
852
853JNIEXPORT void JNICALL Java_CyrusSasl_GenericCommon_jni_1sasl_1set_1client
854  (JNIEnv *env,
855   jobject obj __attribute__((unused)),
856   jint ptr, jbyteArray jarr, jint jport)
857{
858  sasl_conn_t *conn=(sasl_conn_t *) ptr;
859  unsigned char *ip = (*env)->GetByteArrayElements(env, jarr, 0);
860  char out[52];
861  int result;
862
863  sprintf(out, "%d.%d.%d.%d;%d", ip[0], ip[1], ip[2], ip[3], (int)jport);
864
865  result=sasl_setprop(conn, SASL_IPLOCALPORT, out);
866
867  VL(("Set IP_LOCAL: %s: %d\n",out, result));
868
869  /* if not set throw and exception */
870  if (result!=SASL_OK)
871    throwexception(env,result);
872}
873
874/* allocate a secprops structure */
875
876static sasl_security_properties_t *make_secprops(int min,int max)
877{
878  sasl_security_properties_t *ret=(sasl_security_properties_t *)
879    malloc(sizeof(sasl_security_properties_t));
880
881  ret->maxbufsize=1024;
882  ret->min_ssf=min;
883  ret->max_ssf=max;
884
885  ret->security_flags=0;
886  ret->property_names=NULL;
887  ret->property_values=NULL;
888
889  return ret;
890}
891
892
893JNIEXPORT void JNICALL Java_CyrusSasl_GenericCommon_jni_1sasl_1setSecurity
894  (JNIEnv *env,
895   jobject obj __attribute__((unused)),
896   jint ptr, jint minssf, jint maxssf)
897{
898  int result=SASL_FAIL;
899  sasl_conn_t *conn=(sasl_conn_t *) ptr;
900  sasl_security_properties_t *secprops=NULL;
901
902  /* set sec props */
903  secprops=make_secprops(minssf,maxssf);
904
905  if (secprops!=NULL)
906    result=sasl_setprop(conn, SASL_SEC_PROPS, secprops);
907
908  /* if not set throw and exception */
909  if (result!=SASL_OK)
910    throwexception(env,result);
911}
912
913JNIEXPORT jint JNICALL Java_CyrusSasl_GenericCommon_jni_1sasl_1getSecurity
914  (JNIEnv *env,
915   jobject obj __attribute__((unused)),
916   jint ptr)
917{
918    int r = SASL_FAIL;
919    sasl_conn_t *conn = (sasl_conn_t *) ptr;
920    int *ssfp;
921
922    r = sasl_getprop(conn, SASL_SSF, (const void **) &ssfp);
923    if (r != SASL_OK) {
924	throwexception(env, r);
925    }
926
927    return *ssfp;
928}
929
930
931