pike.git / lib / modules / Sql.pmod / pgsql.pike

version» Context lines:

pike.git/lib/modules/Sql.pmod/pgsql.pike:100:   private int warningsdropcount; // Number of uncollected warnings   private int warningscollected;   private int invalidatecache;   private Thread.Queue qportals;   final mixed _delayederror;   private function (:void) readyforquery_cb;      final string _host;   final int _port;   private string database, user, pass; + private string cnonce, ServerSignature;   private Thread.Condition waitforauthready;   final Thread.Mutex _shortmux;   final Thread.Condition _readyforcommit;   final int _waittocommit, _readyforquerycount;      private string _sprintf(int type, void|mapping flags) {    string res=UNDEFINED;    switch(type) {    case 'O':    res=sprintf(DRIVERNAME"(%s@%s:%d/%s,%d,%d)",
pike.git/lib/modules/Sql.pmod/pgsql.pike:197:   //! notice that this function @b{can@} raise exceptions if the db   //! server doesn't respond, if the database doesn't exist or is not   //! accessible to you.   //!   //! @seealso   //! @[Postgres.postgres], @[Sql.Sql], @[select_db()],   //! @url{http://www.postgresql.org/search/?u=%2Fdocs%2Fcurrent%2F&q=client+connection+search_path@}   protected void create(void|string host, void|string database,    void|string user, void|string pass,    void|mapping(string:mixed) options) { -  this::pass = pass; +  this::pass = Standards.IDNA.to_ascii(pass);    if(pass) {    String.secure(pass);    pass = "CENSORED";    } -  this::user = user; +  this::user = Standards.IDNA.to_ascii(user, 1);    this::database = database;    _options = options || ([]);       if(!host) host = PGSQL_DEFAULT_HOST;    if(has_value(host,":") && sscanf(host,"%s:%d",host,_port)!=2)    ERROR("Error in parsing the hostname argument\n");    this::_host = host;       if(!_port)    _port = PGSQL_DEFAULT_PORT;
pike.git/lib/modules/Sql.pmod/pgsql.pike:711:    mapping(string:string) getresponse() {    mapping(string:string) msgresponse=([]);    msglen-=4;    foreach(reads();;string f)    if(sizeof(f))    msgresponse[f[..0]]=f[1..];    PD("%O\n",msgresponse);    return msgresponse;    };    case 'R': { +  void authresponse(array msg) { +  object cs = ci->start(); +  CHAIN(cs)->add_int8('p')->add_hstring(msg, 4, 4); +  cs->sendcmd(SENDOUT); // No flushing, PostgreSQL 9.4 disapproves +  }    PD("Authentication "); -  string sendpass; +     msglen-=4+4; -  int authtype=cr->read_int32(); -  switch(authtype) { +  int authtype, k; +  switch(authtype = cr->read_int32()) {    case 0:    PD("Ok\n"); -  +  if (cnonce) { +  PD("Authentication validation still in progress\n"); +  errtype = PROTOCOLUNSUPPORTED; +  } else {    .pgsql_util.local_backend->remove_call_out(reconnect);    reconnectdelay=0;    cancelsecret=""; -  +  }    break;    case 2:    PD("KerberosV5\n");    errtype=PROTOCOLUNSUPPORTED;    break;    case 3:    PD("ClearTextPassword\n"); -  sendpass=pass; +  authresponse(({pass, 0}));    break;    case 4:    PD("CryptPassword\n");    errtype=PROTOCOLUNSUPPORTED;    break;    case 5:    PD("MD5Password\n");   #ifdef PG_DEBUG    if(msglen<4)    errtype=PROTOCOLERROR;   #endif   #define md5hex(x) String.string2hex(Crypto.MD5.hash(x)) -  sendpass=md5hex(pass+user); -  sendpass="md5"+md5hex(sendpass+cr->read(msglen)); +  authresponse(({"md5", +  md5hex(md5hex(pass + user) + cr->read(msglen)), 0}));   #ifdef PG_DEBUG    msglen=0;   #endif    break;    case 6:    PD("SCMCredential\n");    errtype=PROTOCOLUNSUPPORTED;    break;    case 7:    PD("GSS\n");    errtype=PROTOCOLUNSUPPORTED;    break;    case 9:    PD("SSPI\n");    errtype=PROTOCOLUNSUPPORTED;    break;    case 8:    PD("GSSContinue\n");    errtype=PROTOCOLUNSUPPORTED; -  cancelsecret=cr->read(msglen); // Actually SSauthdata +  cr->read(msglen); // SSauthdata   #ifdef PG_DEBUG    if(msglen<1)    errtype=PROTOCOLERROR;    msglen=0;   #endif    break; -  +  case 10: { +  string word; +  PD("AuthenticationSASL\n"); +  k = 0; +  while (sizeof(word = cr->read_cstring())) { +  switch (word) { +  case "SCRAM-SHA-256": +  k = 1; +  } + #ifdef PG_DEBUG +  msglen -= sizeof(word) + 1; +  if (msglen < 1) +  break; + #endif +  } +  if (k) { +  cnonce = MIME.encode_base64(Random.System().random_string(18)); +  word = "n,,n=,r=" + cnonce; +  authresponse(({ +  "SCRAM-SHA-256", 0, sprintf("%4c", sizeof(word)), word +  })); +  } else +  errtype = PROTOCOLUNSUPPORTED; + #ifdef PG_DEBUG +  if(msglen != 1) +  errtype=PROTOCOLERROR; +  msglen=0; + #endif +  break; +  } +  case 11: { +  string r, salt; +  int iters; + #define HMAC256(key, data) (Crypto.SHA256.HMAC(key)(data)) + #define HASH256(data) (Crypto.SHA256.hash(data)) +  PD("AuthenticationSASLContinue\n"); +  { Stdio.Buffer tb = cr->read_buffer(msglen); +  [r, salt, iters] = tb->sscanf("r=%s,s=%s,i=%d"); + #ifdef PG_DEBUG +  if (sizeof(tb)) +  errtype = PROTOCOLERROR; +  msglen = 0; + #endif +  } +  if (!has_prefix(r, cnonce) || iters <= 0) +  errtype = PROTOCOLERROR; +  else { +  string SaltedPassword; +  if (!(SaltedPassword +  = .pgsql_util.get_salted_password(pass, salt, iters))) { +  SaltedPassword = ServerSignature = +  HMAC256(pass, MIME.decode_base64(salt) + "\0\0\0\1"); +  int i = iters; +  while (--i) +  SaltedPassword ^= ServerSignature +  = HMAC256(pass, ServerSignature); +  .pgsql_util.set_salted_password(pass, salt, iters, +  SaltedPassword); +  } +  salt = sprintf("n=,r=%s,r=%s,s=%s,i=%d,c=biws,r=%s", +  cnonce, r, salt, iters, r); +  ServerSignature = HMAC256(SaltedPassword, "Client Key"); +  authresponse(({ +  sprintf("c=biws,r=%s,p=%s", +  r, MIME.encode_base64( +  ServerSignature +  ^ HMAC256(HASH256(ServerSignature), salt) +  )) +  })); +  ServerSignature = HMAC256(HMAC256(SaltedPassword, "Server Key"), +  salt); +  } +  break; +  } +  case 12: { +  string v; +  PD("AuthenticationSASLFinal\n"); +  Stdio.Buffer tb = cr->read_buffer(msglen); +  [v] = tb->sscanf("v=%s"); +  v = MIME.decode_base64(v); +  if (v != ServerSignature) +  errtype = PROTOCOLERROR; +  else +  cnonce = 0; // Clears cnonce and approves server + #ifdef PG_DEBUG +  if (sizeof(tb)) +  errtype=PROTOCOLERROR; +  msglen=0; + #endif +  break; +  }    default:    PD("Unknown Authentication Method %c\n",authtype);    errtype=PROTOCOLUNSUPPORTED;    break;    }    switch(errtype) { -  case NOERROR: -  if(cancelsecret!="") { -  object cs = ci->start(); -  CHAIN(cs)->add_int8('p')->add_hstring(({sendpass, 0}), 4, 4); -  cs->sendcmd(SENDOUT); -  } -  break; // No flushing here, PostgreSQL 9.4 disapproves +     default:    case PROTOCOLUNSUPPORTED:    ERROR("Unsupported authenticationmethod %c\n",authtype); -  +  case NOERROR:    break;    }    break;    }    case 'K':    msglen-=4+4;backendpid=cr->read_int32();    cancelsecret=cr->read(msglen);   #ifdef PG_DEBUG    PD("BackendKeyData %O\n",cancelsecret);    msglen=0;