Use YAZ_HAVE_XSLT because yaz-config 2.1.23 or later defines it
[yazproxy-moved-to-github.git] / src / yaz-proxy.cpp
index 5c22a64..b1d18c0 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: yaz-proxy.cpp,v 1.65 2006-05-01 09:14:08 adam Exp $
+/* $Id: yaz-proxy.cpp,v 1.70 2006-07-06 11:50:26 adam Exp $
    Copyright (c) 1998-2006, Index Data.
 
 This file is part of the yazproxy.
@@ -59,9 +59,6 @@ using namespace yazpp_1;
 #define strncasecmp _strnicmp
 #endif
 
-#define USE_AUTH_MSG 1
-
-#if USE_AUTH_MSG
 class YAZ_EXPORT Auth_Msg : public IMsg_Thread {
 public:
     int m_ret;
@@ -122,8 +119,6 @@ void Auth_Msg::result()
     delete this;
 }
 
-#endif
-
 void Yaz_Proxy::result_authentication(Z_APDU *apdu, int ret)
 {
     if (apdu == 0 || ret == 0)
@@ -295,6 +290,7 @@ Yaz_Proxy::Yaz_Proxy(IPDU_Observable *the_PDU_Observable,
     m_ref_count = 1;
     m_main_ptr_dec = false;
     m_peername = 0;
+    m_num_msg_threads = 0;
 }
 
 void Yaz_Proxy::inc_ref()
@@ -318,7 +314,7 @@ Yaz_Proxy::~Yaz_Proxy()
     delete m_charset_converter;
     xfree(m_optimize);
 
-#if HAVE_XSLT
+#if YAZ_HAVE_XSLT
     if (m_stylesheet_xsp)
         xsltFreeStylesheet((xsltStylesheetPtr) m_stylesheet_xsp);
 #endif
@@ -358,7 +354,8 @@ int Yaz_Proxy::set_config(const char *config)
     {
         int period = 60;
         m_config->get_generic_info(&m_log_mask, &m_max_clients,
-                                   &m_max_connect, &m_limit_connect, &period);
+                                   &m_max_connect, &m_limit_connect, &period,
+                                   &m_num_msg_threads);
         m_connect.set_period(period);
     }
     return r;
@@ -414,7 +411,7 @@ Yaz_ProxyConfig *Yaz_Proxy::check_reconfigure()
                 int period = 60;
                 cfg->get_generic_info(&m_log_mask, &m_max_clients,
                                       &m_max_connect, &m_limit_connect,
-                                      &period);
+                                      &period, &m_num_msg_threads);
                 m_connect.set_period(period);
             }
         }
@@ -432,6 +429,9 @@ IPDU_Observer *Yaz_Proxy::sessionNotify(IPDU_Observable
 
     char session_str[200];
     const char *peername = the_PDU_Observable->getpeername();
+    if (!peername)
+        peername = "nullpeer";
+
     if (m_log_mask & PROXY_LOG_IP_CLIENT)
         sprintf(session_str, "%ld:%d %.80s %d ",
                 (long) time(0), m_session_no, peername, 0);
@@ -453,9 +453,13 @@ IPDU_Observer *Yaz_Proxy::sessionNotify(IPDU_Observable
     new_proxy->m_max_clients = m_max_clients;
     new_proxy->m_log_mask = m_log_mask;
     new_proxy->m_session_no = m_session_no;
+    new_proxy->m_num_msg_threads = m_num_msg_threads;
 
+#if 0
+    // in case we want to watch a particular client..
     if (!strcmp(peername, "tcp:163.121.19.82")) // NIS GROUP
         new_proxy->m_log_mask = 255;
+#endif
 
     new_proxy->set_APDU_log(get_APDU_log());
     if (new_proxy->m_log_mask & PROXY_LOG_APDU_CLIENT)
@@ -467,8 +471,12 @@ IPDU_Observer *Yaz_Proxy::sessionNotify(IPDU_Observable
     new_proxy->set_proxy_negotiation(m_proxy_negotiation_charset,
         m_proxy_negotiation_lang, m_proxy_negotiation_default_charset);
     // create thread object the first time we get an incoming connection
-    if (!m_my_thread)
-        m_my_thread = new Msg_Thread(m_socket_observable, 1);
+    if (!m_my_thread && m_num_msg_threads > 0)
+    {
+        yaz_log (YLOG_LOG, "%sStarting message thread management. number=%d",
+                 session_str, m_num_msg_threads);
+        m_my_thread = new Msg_Thread(m_socket_observable, m_num_msg_threads);
+    }
     new_proxy->m_my_thread = m_my_thread;
     return new_proxy;
 }
@@ -869,7 +877,7 @@ int Yaz_Proxy::convert_xsl(Z_NamePlusRecordList *p, Z_APDU *apdu)
 
 void Yaz_Proxy::convert_xsl_delay()
 {
-#if HAVE_XSLT
+#if YAZ_HAVE_XSLT
     Z_NamePlusRecord *npr = m_stylesheet_nprl->records[m_stylesheet_offset];
     if (npr->which == Z_NamePlusRecord_databaseRecord)
     {
@@ -912,7 +920,7 @@ void Yaz_Proxy::convert_xsl_delay()
     {
         m_timeout_mode = timeout_normal;
         m_stylesheet_nprl = 0;
-#if HAVE_XSLT
+#if YAZ_HAVE_XSLT
         if (m_stylesheet_xsp)
             xsltFreeStylesheet((xsltStylesheetPtr) m_stylesheet_xsp);
 #endif
@@ -1136,6 +1144,10 @@ int Yaz_Proxy::send_http_response(int code)
         z_HTTP_header_add(o, &hres->headers, "Connection", "Keep-Alive");
     else
         timeout(0);
+    if (code == 401)
+        z_HTTP_header_add(o, &hres->headers, "WWW-Authenticate", 
+                          "Basic realm=\"YAZ Proxy\"");
+
 
     if (m_log_mask & PROXY_LOG_REQ_CLIENT)
     {
@@ -1170,7 +1182,7 @@ int Yaz_Proxy::send_srw_response(Z_SRW_PDU *srw_pdu, int http_code /* = 200 */)
         z_HTTP_header_add(o, &hres->headers, "WWW-Authenticate", "Basic realm=\"YAZ Proxy\"");
 
     static Z_SOAP_Handler soap_handlers[2] = {
-#if HAVE_XSLT
+#if YAZ_HAVE_XSLT
         {"http://www.loc.gov/zing/srw/", 0,
          (Z_SOAP_fun) yaz_srw_codec},
 #endif
@@ -2409,6 +2421,44 @@ int Yaz_Proxy::handle_authentication(Z_APDU *apdu)
     return ret;
 }
 
+int Yaz_Proxy::handle_global_authentication(Z_APDU *apdu)
+{
+    if (apdu->which != Z_APDU_initRequest)
+        return 1;  // pass if no init request
+    Z_InitRequest *req = apdu->u.initRequest;
+
+    Yaz_ProxyConfig *cfg = check_reconfigure();
+    if (!cfg)
+        return 1;  // pass if no config
+
+    int ret;
+    if (req->idAuthentication == 0)
+    {
+        ret = cfg->global_client_authentication(0, 0, 0,
+                                                m_peername);
+    }
+    else if (req->idAuthentication->which == Z_IdAuthentication_idPass)
+    {
+        ret = cfg->global_client_authentication(
+            req->idAuthentication->u.idPass->userId,
+            req->idAuthentication->u.idPass->groupId,
+            req->idAuthentication->u.idPass->password,
+            m_peername);
+    }
+    else if (req->idAuthentication->which == Z_IdAuthentication_open)
+    {
+        char user[64], pass[64];
+        *user = '\0';
+        *pass = '\0';
+        sscanf(req->idAuthentication->u.open, "%63[^/]/%63s", user, pass);
+        ret = cfg->global_client_authentication(user, 0, pass,
+                                                m_peername);
+    }
+    else
+        ret = cfg->global_client_authentication(0, 0, 0, m_peername);
+    return ret;
+}
+
 Z_APDU *Yaz_Proxy::handle_syntax_validation(Z_APDU *apdu)
 {
     m_marcxml_mode = none;
@@ -2449,7 +2499,7 @@ Z_APDU *Yaz_Proxy::handle_syntax_validation(Z_APDU *apdu)
         {
             m_parent->low_socket_close();
 
-#if HAVE_XSLT
+#if YAZ_HAVE_XSLT
             if (m_stylesheet_xsp)
                 xsltFreeStylesheet((xsltStylesheetPtr) m_stylesheet_xsp);
             m_stylesheet_xsp = xsltParseStylesheetFile((const xmlChar*)
@@ -2526,7 +2576,7 @@ Z_APDU *Yaz_Proxy::handle_syntax_validation(Z_APDU *apdu)
         {
             m_parent->low_socket_close();
 
-#if HAVE_XSLT
+#if YAZ_HAVE_XSLT
             if (m_stylesheet_xsp)
                 xsltFreeStylesheet((xsltStylesheetPtr) m_stylesheet_xsp);
             m_stylesheet_xsp = xsltParseStylesheetFile((const xmlChar*)
@@ -3137,21 +3187,24 @@ void Yaz_Proxy::handle_init(Z_APDU *apdu)
     }
     m_client->m_init_flag = 1;
 
-#if USE_AUTH_MSG
-    Auth_Msg *m = new Auth_Msg;
-    m->m_proxy = this;
-    z_APDU(odr_encode(), &apdu, 0, "encode");
-    char *apdu_buf = odr_getbuf(odr_encode(), &m->m_apdu_len, 0);
-    m->m_apdu_buf = (char*) nmem_malloc(m->m_nmem, m->m_apdu_len);
-    memcpy(m->m_apdu_buf, apdu_buf, m->m_apdu_len);
-    odr_reset(odr_encode());
-
-    inc_ref();
-    m_my_thread->put(m);
-#else
-    int ret = handle_authentication(apdu);
-    result_authentication(apdu, ret);
-#endif
+    if (m_num_msg_threads && m_my_thread)
+    {
+        Auth_Msg *m = new Auth_Msg;
+        m->m_proxy = this;
+        z_APDU(odr_encode(), &apdu, 0, "encode");
+        char *apdu_buf = odr_getbuf(odr_encode(), &m->m_apdu_len, 0);
+        m->m_apdu_buf = (char*) nmem_malloc(m->m_nmem, m->m_apdu_len);
+        memcpy(m->m_apdu_buf, apdu_buf, m->m_apdu_len);
+        odr_reset(odr_encode());
+        
+        inc_ref();
+        m_my_thread->put(m);
+    }
+    else
+    {
+        int ret = handle_authentication(apdu);
+        result_authentication(apdu, ret);
+    }
 }
 
 void Yaz_Proxy::handle_incoming_Z_PDU(Z_APDU *apdu)
@@ -3181,6 +3234,23 @@ void Yaz_Proxy::handle_incoming_Z_PDU(Z_APDU *apdu)
     if (apdu->which == Z_APDU_searchRequest)
         m_search_stat.add_bytes(1);
 
+    // Handle global authentication
+    if (!handle_global_authentication(apdu))
+    {
+        if (m_http_version)
+        {   // HTTP. Send unauthorized
+            send_http_response(401);
+            return;
+        }
+        else
+        {
+            // Z39.50 just shutdown
+            timeout(0);
+            return;
+        }
+        return;
+    }
+
     // Determine our client.
     Z_OtherInformation **oi;
     get_otherInfoAPDU(apdu, &oi);