a580e12000-09-27Fredrik Hübinette (Hubbe) #pike __REAL_VERSION__
a20af62000-09-26Fredrik Hübinette (Hubbe) 
aa370a1999-04-24Johan Schön // LDAP client protocol implementation for Pike. //
563bd72004-01-11Martin Nilsson // $Id: protocol.pike,v 1.11 2004/01/11 00:49:03 nilsson Exp $
aa370a1999-04-24Johan Schön // // Honza Petrous, hop@unibase.cz // // ---------------------------------------------------------------------- // // History: // // v1.9 1999-02-19 created separate file // - improved checking of readed bytes in 'readmsg' // v1.9.1.1 // 1999-03-21 - changed FILE to File (unbuffered) // - some inactive code // // v1.10 1999-03-28 - rewritten methods 'readmsg' & 'writemsg' // to new method 'xchgmsg' // - added core for async operation //
92dbd31999-08-24Fredrik Hübinette (Hubbe) #if constant(Standards.ASN1.Types.asn1_integer)
aa370a1999-04-24Johan Schön  #include "ldap_globals.h" #include "ldap_errors.h" inherit Stdio.File : ldap; // private variables int next_id = 1; // message id counter int ldap_version = LDAP_DEFAULT_VERSION; // actually used protocol vers. string ldap_rem_errstr = LDAP_SUCCESS_STR; // last remote error description int ldap_errno = LDAP_SUCCESS; // last error code /*private*/ string readbuf=""; // read buffer private int ok; // read buffer status /*private*/ string writebuf=""; // write buffer // private written; // count of written chars private function con_ok, con_fail; // async callback functions object conthread; // thread connection array extra_args; // not used, yet // /*private*/ int errno; int connected = 0;
0668612001-09-14Honza Petrous  object ldapfd; // helper fd
aa370a1999-04-24Johan Schön  int seterr(int errno) { // Sets ldap_err* variables and returns errno //ldap_rem_errstr = errstr; ldap_errno = errno;
6659452003-09-01Martin Nilsson  return errno;
aa370a1999-04-24Johan Schön  }
0b5e392002-07-22H. William Welliver III  //! //! Returns error number of last transaction. //! //! @seealso //! @[LDAP.protocol.error_string]
6659452003-09-01Martin Nilsson  int error_number() { return ldap_errno; }
aa370a1999-04-24Johan Schön 
0b5e392002-07-22H. William Welliver III  //! //! Returns error description of search result. //! //! @seealso //! @[LDAP.protocol.error_number]
6659452003-09-01Martin Nilsson  string error_string() { return ldap_errlist[ldap_errno]; }
aa370a1999-04-24Johan Schön 
6659452003-09-01Martin Nilsson  array error() { return ({error_number(), error_string()}); }
aa370a1999-04-24Johan Schön  static void read_answer() { // ---------------------- // Reads LDAP PDU (with defined msgid) from the server int msglen = 0, ix, ofs; string s, shlp;
ead9722003-01-20Martin Nilsson  if(sizeof(readbuf) < 2)
0668612001-09-14Honza Petrous  readbuf = ldapfd->read(2); // 1. byte = 0x0C, 2. byte = msglen
ead9722003-01-20Martin Nilsson  if (intp(readbuf) || (sizeof(readbuf) < 2)) {
aa370a1999-04-24Johan Schön  seterr (LDAP_TIMEOUT); DWRITE_HI("protocol.read_anwer: ERROR: connection timeout.\n"); THROW(({"LDAP: connection timeout.\n",backtrace()}));
6659452003-09-01Martin Nilsson  //return -ldap_errno;
aa370a1999-04-24Johan Schön  return; } if (readbuf[0] != '0') { seterr (LDAP_PROTOCOL_ERROR); DWRITE_HI("protocol.read_anwer: ERROR: retv=<"+sprintf("%O",readbuf)+">\n"); THROW(({"LDAP: Protocol mismatch.\n",backtrace()}));
6659452003-09-01Martin Nilsson  //return -ldap_errno;
aa370a1999-04-24Johan Schön  return; } DWRITE(sprintf("protocol.read_anwer: sizeof = %d\n", sizeof(readbuf))); msglen = readbuf[1]; ofs = 2; if (msglen & 0x80) { // > 0x7f if (msglen == 0x80) { // RFC not allows unexplicitly defined length seterr (LDAP_PROTOCOL_ERROR); THROW(({"LDAP: Protocol mismatch.\n",backtrace()}));
6659452003-09-01Martin Nilsson  //return -ldap_errno;
aa370a1999-04-24Johan Schön  return; } ofs = (msglen & 0x7f) + 2;
ead9722003-01-20Martin Nilsson  ix = ofs - sizeof(readbuf);
aa370a1999-04-24Johan Schön  if(ix > 0)
0668612001-09-14Honza Petrous  s = ldapfd->read(ix);
ead9722003-01-20Martin Nilsson  if (!s || (sizeof(s) < ix)) {
aa370a1999-04-24Johan Schön  seterr (LDAP_PROTOCOL_ERROR); THROW(({"LDAP: Protocol mismatch.\n",backtrace()}));
6659452003-09-01Martin Nilsson  //return -ldap_errno;
aa370a1999-04-24Johan Schön  return; } readbuf += s; msglen = 0; // !!! RESTRICTION: 2^32 !!! shlp = reverse(readbuf[2..ofs]);
ead9722003-01-20Martin Nilsson  for (ix=0; ix<sizeof(shlp); ix++) {
aa370a1999-04-24Johan Schön  msglen += shlp[ix]*(1<<(ix*8)); } }
ead9722003-01-20Martin Nilsson  ix = (ofs + msglen) - sizeof(readbuf);
aa370a1999-04-24Johan Schön  if(ix > 0)
0668612001-09-14Honza Petrous  s = ldapfd->read(ix);
ead9722003-01-20Martin Nilsson  if (!s || (sizeof(s) < ix)) {
aa370a1999-04-24Johan Schön  seterr (LDAP_SERVER_DOWN); THROW(({"LDAP: connection closed by server.\n",backtrace()}));
6659452003-09-01Martin Nilsson  //return -ldap_errno;
aa370a1999-04-24Johan Schön  return; } readbuf += s; //DWRITE(sprintf("protocol.read_anwer: %s\n", .ldap_privates.ldap_der_decode(readbuf)->debug_string())); DWRITE("protocol.read_anwer: ok=1.\n"); ok = 1; if(con_ok)
563bd72004-01-11Martin Nilsson  con_ok(this, @extra_args);
aa370a1999-04-24Johan Schön  } static int is_whole_pdu() { // ---------------------- // Check if LDAP PDU is complete in 'readbuf' int msglen, ix, ofs; string shlp;
ead9722003-01-20Martin Nilsson  if (sizeof(readbuf) < 3)
6659452003-09-01Martin Nilsson  return 0; // PDU have min. 3 bytes
aa370a1999-04-24Johan Schön  if (readbuf[0] != '0')
6659452003-09-01Martin Nilsson  return 1; // PDU has bad header -> forced execution
aa370a1999-04-24Johan Schön  msglen = readbuf[1]; if (msglen & 0x80) { // > 0x7f if (msglen == 0x80)
6659452003-09-01Martin Nilsson  return 1; // forced execution
aa370a1999-04-24Johan Schön  ofs = (msglen & 0x7f) + 2;
ead9722003-01-20Martin Nilsson  ix = ofs - sizeof(readbuf);
aa370a1999-04-24Johan Schön  if(ix > 0)
6659452003-09-01Martin Nilsson  return 0; // incomplete PDU
aa370a1999-04-24Johan Schön  msglen = 0; shlp = reverse(readbuf[2..ofs]);
ead9722003-01-20Martin Nilsson  for (ix=0; ix<sizeof(shlp); ix++) {
aa370a1999-04-24Johan Schön  msglen += shlp[ix]*(1<<(ix*8)); } }
ead9722003-01-20Martin Nilsson  ix = (ofs + msglen) - sizeof(readbuf);
aa370a1999-04-24Johan Schön  if(ix > 0)
6659452003-09-01Martin Nilsson  return 0; // incomplete PDU
aa370a1999-04-24Johan Schön 
6659452003-09-01Martin Nilsson  return 1;
aa370a1999-04-24Johan Schön  }
0668612001-09-14Honza Petrous  void create(object fd) { // ------------------- ldapfd = fd;
aa370a1999-04-24Johan Schön  } string|int do_op(object msgop) { // --------------------------- // Make LDAP PDU envelope for 'msgop', send it and read answer ... object msgval; object msgid; int rv = 0, msgnum; string s; //THREAD_LOCK msgnum = next_id++; //THREAD_UNLOCK msgid = Standards.ASN1.Types.asn1_integer(msgnum); msgval = Standards.ASN1.Types.asn1_sequence(({msgid, msgop})); if (objectp(msgval)) { DWRITE(sprintf("protocol.do_op: msg = [%d]\n",sizeof(msgval->get_der()))); } else DWRITE("protocol.do_op: msg is null!\n"); // call_out writebuf = msgval->get_der();
0668612001-09-14Honza Petrous  rv = ldapfd->write(writebuf); // !!!!! - jak rozlisit async a sync ????
aa370a1999-04-24Johan Schön  // call_out if (rv < 2) { seterr (LDAP_SERVER_DOWN); THROW(({"LDAP: connection closed by server.\n",backtrace()}));
6659452003-09-01Martin Nilsson  return -ldap_errno;
aa370a1999-04-24Johan Schön  } DWRITE(sprintf("protocol.do_op: write OK [%d bytes].\n",rv)); msgval = 0; msgid = 0; writebuf= ""; readbuf= ""; // !!! NEni to pozde ? //`()(); read_answer(); // now is all in 'readbuf'
6659452003-09-01Martin Nilsson  return readbuf;
aa370a1999-04-24Johan Schön  } /* ------------ legacy support -----------------*/ string|int readmsg(int msgid) { // Reads LDAP PDU (with defined msgid) from server, checks msgid ... int msglen = 0, ix;
89cbf81999-12-30Henrik Grubbström (Grubba)  string|int retv;
1498051999-12-30Henrik Grubbström (Grubba)  string s, shlp;
aa370a1999-04-24Johan Schön 
0668612001-09-14Honza Petrous  retv = ldapfd->read(2); // 1. byte = 0x0C, 2. byte = msglen
aa370a1999-04-24Johan Schön  if (intp(retv) && (retv == -1)) { seterr (LDAP_TIMEOUT); DWRITE_HI("protocol.readmsg: ERROR: connection timeout.\n"); THROW(({"LDAP: connection timeout.\n",backtrace()}));
6659452003-09-01Martin Nilsson  return -ldap_errno;
aa370a1999-04-24Johan Schön  } if (!retv || (sizeof(retv) != 2) || (retv[0] != '0')) { seterr (LDAP_PROTOCOL_ERROR); DWRITE_HI("protocol.readmsg: ERROR: retv=<"+sprintf("%O",retv)+">\n"); THROW(({"LDAP: Protocol mismatch.\n",backtrace()}));
6659452003-09-01Martin Nilsson  return -ldap_errno;
aa370a1999-04-24Johan Schön  } DWRITE(sprintf("protocol.readmsg: sizeof = %d\n", sizeof(retv))); msglen = retv[1]; if (msglen & 0x80) { // > 0x7f if (msglen == 0x80) { // RFC not allows unexplicitly defined length seterr (LDAP_PROTOCOL_ERROR); THROW(({"LDAP: Protocol mismatch.\n",backtrace()}));
6659452003-09-01Martin Nilsson  return -ldap_errno;
aa370a1999-04-24Johan Schön  }
0668612001-09-14Honza Petrous  s = ldapfd->read(msglen & 0x7f);
aa370a1999-04-24Johan Schön  if (!s) { seterr (LDAP_PROTOCOL_ERROR); THROW(({"LDAP: Protocol mismatch.\n",backtrace()}));
6659452003-09-01Martin Nilsson  return -ldap_errno;
aa370a1999-04-24Johan Schön  } retv += s; msglen = 0; // !!! RESTRICTION: 2^32 !!! shlp = reverse(s); for (ix=0; ix<sizeof(shlp); ix++) { msglen += shlp[ix]*(1<<(ix*8)); } }
0668612001-09-14Honza Petrous  s = ldapfd->read(msglen);
aa370a1999-04-24Johan Schön  if (!s | (sizeof(s) < msglen)) { seterr (LDAP_SERVER_DOWN); THROW(({"LDAP: connection closed by server.\n",backtrace()}));
6659452003-09-01Martin Nilsson  return -ldap_errno;
aa370a1999-04-24Johan Schön  } retv += s; DWRITE(sprintf("protocol.readmsg: %s\n", .ldap_privates.ldap_der_decode(retv)->debug_string()));
6659452003-09-01Martin Nilsson  return retv;
aa370a1999-04-24Johan Schön  } int writemsg(object msgop) { // Make LDAP PDU envelope for 'msgop' and send it object msgval; object msgid; int rv = 0, msgnum; string s; //THREAD_LOCK msgnum = next_id++; //THREAD_UNLOCK msgid = Standards.ASN1.Types.asn1_integer(msgnum); msgval = Standards.ASN1.Types.asn1_sequence(({msgid, msgop})); if (objectp(msgval)) { DWRITE(sprintf("protocol.writemsg: msg = [%d]\n",sizeof(msgval->get_der()))); } else DWRITE("protocol.writemsg: msg is null!\n"); // call_out
0668612001-09-14Honza Petrous  rv = ldapfd->write(msgval->get_der());
aa370a1999-04-24Johan Schön  // call_out if (rv < 2) { seterr (LDAP_SERVER_DOWN); THROW(({"LDAP: connection closed by server.\n",backtrace()}));
6659452003-09-01Martin Nilsson  return -ldap_errno;
aa370a1999-04-24Johan Schön  } DWRITE(sprintf("protocol.writemsg: write OK [%d bytes].\n",rv)); msgval = 0; msgid = 0;
6659452003-09-01Martin Nilsson  return msgnum;
aa370a1999-04-24Johan Schön  }
92dbd31999-08-24Fredrik Hübinette (Hubbe) #endif