• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KIOSlave

httpauthentication.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002     Copyright (C) 2008, 2009 Andreas Hartmetz <ahartmetz@gmail.com>
00003 
00004     This library is free software; you can redistribute it and/or
00005     modify it under the terms of the GNU Library General Public
00006     License as published by the Free Software Foundation; either
00007     version 2 of the License, or (at your option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012     Library General Public License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to
00016     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017     Boston, MA 02110-1301, USA.
00018 */
00019 
00020 
00021 #include "httpauthentication.h"
00022 
00023 
00024 // keys on even indexes, values on odd indexes. Reduces code expansion for the templated
00025 // alternatives.
00026 static QList<QByteArray> parseChallenge(const QByteArray &ba, QByteArray *scheme)
00027 {
00028     QList<QByteArray> values;
00029     const int len = ba.count();
00030     const char *b = ba.constData();
00031     int start = 0;
00032     int end = 0;
00033 
00034     // parse scheme
00035     while (start < len && (b[start] == ' ' || b[start] == '\t')) {
00036         start++;
00037     }
00038     end = start;
00039     while (end < len && (b[end] != ' ' && b[end] != '\t')) {
00040         end++;
00041     }
00042     if (scheme) {
00043         *scheme = QByteArray(b + start, end - start);
00044     }
00045 
00046     while (end < len) {
00047         start = end;
00048         // parse key
00049         while (start < len && (b[start] == ' ' || b[start] == '\t')) {
00050             start++;
00051         }
00052         end = start;
00053         while (end < len && b[end] != '=') {
00054             end++;
00055         }
00056         values.append(QByteArray(b + start, end - start));
00057         if (end == len) {
00058             break;
00059         }
00060 
00061         // parse value
00062         start = end + 1;    //skip '='
00063         while (start < len && (b[start] == ' ' || b[start] == '\t')) {
00064             start++;
00065         }
00066         if (start + 1 < len && b[start] == '"') {
00067             end = ++start;
00068             //quoted string
00069             while (end < len && b[end] != '"') {
00070                 end++;
00071             }
00072             values.append(QByteArray(b + start, end - start));
00073             //the quoted string has ended, but only a comma ends a key-value pair
00074             while (end < len && b[end] != ',') {
00075                 end++;
00076             }
00077         } else {
00078             end = start;
00079             //unquoted string
00080             while (end < len && b[end] != ',') {
00081                 end++;
00082             }
00083             values.append(QByteArray(b + start, end - start));
00084         }
00085         // end may point beyond the buffer already here
00086         end++;  // skip comma
00087     }
00088     // ensure every key has a value
00089     if (values.count() % 2) {
00090         values.removeLast();
00091     }
00092     return values;
00093 }
00094 
00095 
00096 static QByteArray valueForKey(const QList<QByteArray> &ba, const QByteArray &key)
00097 {
00098     for (int i = 0; i + 1 < ba.count(); i += 2) {
00099         if (ba[i] == key) {
00100             return ba[i + 1];
00101         }
00102     }
00103     return QByteArray();
00104 }
00105 
00106 
00107 QByteArray KAbstractHttpAuthentication::bestOffer(const QList<QByteArray> &offers)
00108 {
00109     // choose the most secure auth scheme offered
00110     QByteArray negotiateOffer;
00111     QByteArray digestOffer;
00112     QByteArray ntlmOffer;
00113     QByteArray basicOffer;
00114     foreach (const QByteArray &offer, offers) {
00115         QByteArray scheme = offer.mid(0, 10).toLower();
00116 #ifdef HAVE_LIBGSSAPI
00117         if (scheme.startsWith("negotiate")) {
00118             negotiateOffer = offer;
00119         } else
00120 #endif
00121         if (scheme.startsWith("digest")) {
00122             digestOffer = offer;
00123         } else if (scheme.startsWith("ntlm")) {
00124             ntlmOffer = offer;
00125         } else if (scheme.startsWith("basic")) {
00126             basicOffer = offer;
00127         }
00128     }
00129 
00130     if (!negotiateOffer.isEmpty()) {
00131         return negotiateOffer;
00132     } else if (!digestOffer.isEmpty()) {
00133         return digestOffer;
00134     } else if (!ntlmOffer.isEmpty()) {
00135         return ntlmOffer;
00136     }
00137     return basicOffer;  //empty or not...
00138 }
00139 
00140 
00141 KAbstractHttpAuthentication *KAbstractHttpAuthentication::newAuth(const QByteArray &offer)
00142 {
00143     QByteArray scheme = offer.mid(0, 10).toLower();
00144 #ifdef HAVE_LIBGSSAPI
00145     if (scheme.startsWith("negotiate")) {
00146         return new KHttpNegotiateAuthentication();
00147     } else
00148 #endif
00149     if (scheme.startsWith("digest")) {
00150         return new KHttpDigestAuthentication();
00151     } else if (scheme.startsWith("ntlm")) {
00152         return new KHttpNtlmAuthentication();
00153     } else if (scheme.startsWith("basic")) {
00154         return new KHttpBasicAuthentication();
00155     }
00156     return 0;
00157 }
00158 
00159 
00160 void KAbstractHttpAuthentication::reset()
00161 {
00162     m_scheme.clear();
00163     m_challenge.clear();
00164     m_resource.clear();
00165     m_httpMethod.clear();
00166     m_isError = false;
00167     m_needCredentials = true;
00168     m_forceKeepAlive = false;
00169     m_forceDisconnect = false;
00170     m_headerFragment.clear();
00171     m_username.clear();
00172     m_password.clear();
00173 }
00174 
00175 
00176 void KAbstractHttpAuthentication::setChallenge(const QByteArray &c, const KUrl &resource,
00177                                                const QByteArray &httpMethod)
00178 {
00179     reset();
00180     m_challenge = parseChallenge(c, &m_scheme);
00181     Q_ASSERT(m_scheme.toLower() == scheme().toLower());
00182     m_resource = resource;
00183     m_httpMethod = httpMethod;
00184 }
00185 
00186 
00187 QString KAbstractHttpAuthentication::realm() const
00188 {
00189     QByteArray realm = valueForKey(m_challenge, "realm");
00190     if (KGlobal::locale()->language().contains("ru")) {
00191         //for sites like lib.homelinux.org
00192         return QTextCodec::codecForName("CP1251")->toUnicode(realm);
00193     }
00194     return QString::fromLatin1(realm);
00195 }
00196 
00197 
00198 void KAbstractHttpAuthentication::authInfoBoilerplate(KIO::AuthInfo *a) const
00199 {
00200     a->verifyPath = true;  //### research this
00201     a->url = m_resource;
00202     a->realmValue = realm();
00203     a->username = m_username;
00204     a->password = m_password;
00205 }
00206 
00207 
00208 void KAbstractHttpAuthentication::generateResponseCommon(const QString &user, const QString &password)
00209 {
00210     if ((m_needCredentials && (user.isEmpty() || password.isEmpty())) ||
00211         m_scheme.isEmpty() || m_httpMethod.isEmpty()) {
00212         m_isError = true;
00213         return;
00214     }
00215 
00216     if (m_needCredentials) {
00217         m_username = user;
00218         m_password = password;
00219     }
00220     m_isError = false;
00221     // we could leave m_needCredentials value alone; this is just defensive coding.
00222     m_needCredentials = true;
00223     m_forceKeepAlive = false;
00224     m_forceDisconnect = false;
00225 }
00226 
00227 
00228 QByteArray KHttpBasicAuthentication::scheme() const
00229 {
00230     return "Basic";
00231 }
00232 
00233 
00234 void KHttpBasicAuthentication::fillKioAuthInfo(KIO::AuthInfo *ai) const
00235 {
00236     authInfoBoilerplate(ai);
00237 }
00238 
00239 
00240 void KHttpBasicAuthentication::generateResponse(const QString &user, const QString &password)
00241 {
00242     generateResponseCommon(user, password);
00243     if (m_isError) {
00244         return;
00245     }
00246 
00247     m_headerFragment = "Basic ";
00248     m_headerFragment += KCodecs::base64Encode(m_username.toLatin1() + ':' + m_password.toLatin1());
00249     m_headerFragment += "\r\n";
00250     return;
00251 }
00252 
00253 
00254 QByteArray KHttpDigestAuthentication::scheme() const
00255 {
00256     return "Digest";
00257 }
00258 
00259 
00260 void KHttpDigestAuthentication::setChallenge(const QByteArray &c, const KUrl &resource,
00261                                              const QByteArray &httpMethod)
00262 {
00263     QString oldUsername;
00264     QString oldPassword;
00265     if (valueForKey(m_challenge, "stale").toLower() == "true") {
00266         // stale nonce: the auth failure that triggered this round of authentication is an artifact
00267         // of digest authentication. the credentials are probably still good, so keep them.
00268         oldUsername = m_username;
00269         oldPassword = m_password;
00270     }
00271     KAbstractHttpAuthentication::setChallenge(c, resource, httpMethod);
00272     if (!oldUsername.isEmpty() && !oldPassword.isEmpty()) {
00273         // keep credentials *and* don't ask for new ones
00274         m_needCredentials = false;
00275         m_username = oldUsername;
00276         m_password = oldPassword;
00277     }
00278 }
00279 
00280 
00281 void KHttpDigestAuthentication::fillKioAuthInfo(KIO::AuthInfo *ai) const
00282 {
00283     authInfoBoilerplate(ai);
00284 }
00285 
00286 
00287 struct DigestAuthInfo
00288 {
00289     QByteArray nc;
00290     QByteArray qop;
00291     QByteArray realm;
00292     QByteArray nonce;
00293     QByteArray method;
00294     QByteArray cnonce;
00295     QByteArray username;
00296     QByteArray password;
00297     KUrl::List digestURIs;
00298     QByteArray algorithm;
00299     QByteArray entityBody;
00300 };
00301 
00302 
00303 //calculateResponse() from the original HTTPProtocol
00304 static QByteArray calculateResponse(const DigestAuthInfo &info, const KUrl &resource)
00305 {
00306   kDebug(7113) << info.nc << info.qop << info.realm << info.nonce << info.method << info.cnonce
00307                << info.username << info.password << info.algorithm << info.entityBody;
00308   foreach (const KUrl &u, info.digestURIs) {
00309       kDebug(7113) << u;
00310   }
00311   kDebug(7113);
00312   KMD5 md;
00313   QByteArray HA1;
00314   QByteArray HA2;
00315 
00316   // Calculate H(A1)
00317   QByteArray authStr = info.username;
00318   authStr += ':';
00319   authStr += info.realm;
00320   authStr += ':';
00321   authStr += info.password;
00322   md.update( authStr );
00323 
00324   if ( info.algorithm.toLower() == "md5-sess" )
00325   {
00326     authStr = md.hexDigest();
00327     authStr += ':';
00328     authStr += info.nonce;
00329     authStr += ':';
00330     authStr += info.cnonce;
00331     md.reset();
00332     md.update( authStr );
00333   }
00334   HA1 = md.hexDigest();
00335 
00336   kDebug(7113) << "A1 => " << HA1;
00337 
00338   // Calcualte H(A2)
00339   authStr = info.method;
00340   authStr += ':';
00341   authStr += resource.encodedPathAndQuery(KUrl::LeaveTrailingSlash, KUrl::AvoidEmptyPath).toLatin1();
00342   if ( info.qop == "auth-int" )
00343   {
00344     authStr += ':';
00345     authStr += info.entityBody;
00346   }
00347   md.reset();
00348   md.update( authStr );
00349   HA2 = md.hexDigest();
00350 
00351   kDebug(7113) << "A2 => " << HA2;
00352 
00353   // Calcualte the response.
00354   authStr = HA1;
00355   authStr += ':';
00356   authStr += info.nonce;
00357   authStr += ':';
00358   if ( !info.qop.isEmpty() )
00359   {
00360     authStr += info.nc;
00361     authStr += ':';
00362     authStr += info.cnonce;
00363     authStr += ':';
00364     authStr += info.qop;
00365     authStr += ':';
00366   }
00367   authStr += HA2;
00368   md.reset();
00369   md.update( authStr );
00370 
00371   QByteArray Response = md.hexDigest();
00372 
00373   kDebug(7113) << "Response => " << Response;
00374   return Response;
00375 }
00376 
00377 
00378 void KHttpDigestAuthentication::generateResponse(const QString &user, const QString &password)
00379 {
00380     generateResponseCommon(user, password);
00381     if (m_isError) {
00382         return;
00383     }
00384 
00385 // magic starts here (this part is slightly modified from the original in HTTPProtocol)
00386 
00387     DigestAuthInfo info;
00388 
00389     info.username = m_username.toLatin1();  //### charset breakage
00390     info.password = m_password.toLatin1();  //###
00391 
00392     // info.entityBody = p;  // FIXME: send digest of data for POST action ??
00393     info.realm = "";
00394     info.nonce = "";
00395     info.qop = "";
00396 
00397     // cnonce is recommended to contain about 64 bits of entropy
00398     info.cnonce = KRandom::randomString(16).toLatin1();
00399 
00400     // HACK: Should be fixed according to RFC 2617 section 3.2.2
00401     info.nc = "00000001";
00402 
00403     // Set the method used...
00404     info.method = m_httpMethod;
00405 
00406     // Parse the Digest response....
00407     info.realm = valueForKey(m_challenge, "realm");
00408 
00409     info.algorithm = valueForKey(m_challenge, "algorith");
00410     if (info.algorithm.isEmpty()) {
00411         info.algorithm = valueForKey(m_challenge, "algorithm");
00412     }
00413     if (info.algorithm.isEmpty()) {
00414         info.algorithm = "MD5";
00415     }
00416 
00417     foreach (const QByteArray &path, valueForKey(m_challenge, "domain").split(' ')) {
00418         KUrl u(m_resource, QString::fromLatin1(path));
00419         if (u.isValid()) {
00420             info.digestURIs.append(u);
00421         }
00422     }
00423 
00424     info.nonce = valueForKey(m_challenge, "nonce");
00425     QByteArray opaque = valueForKey(m_challenge, "opaque");
00426     info.qop = valueForKey(m_challenge, "qop");
00427 
00428     if (info.realm.isEmpty() || info.nonce.isEmpty()) {
00429         // ### proper error return
00430         m_isError = true;
00431         return;
00432     }
00433 
00434   // If the "domain" attribute was not specified and the current response code
00435   // is authentication needed, add the current request url to the list over which
00436   // this credential can be automatically applied.
00437   if (info.digestURIs.isEmpty() /*###&& (m_request.responseCode == 401 || m_request.responseCode == 407)*/)
00438     info.digestURIs.append (m_resource);
00439   else
00440   {
00441     // Verify whether or not we should send a cached credential to the
00442     // server based on the stored "domain" attribute...
00443     bool send = true;
00444 
00445     // Determine the path of the request url...
00446     QString requestPath = m_resource.directory(KUrl::AppendTrailingSlash | KUrl::ObeyTrailingSlash);
00447     if (requestPath.isEmpty())
00448       requestPath = "/";
00449 
00450     foreach (const KUrl &u, info.digestURIs)
00451     {
00452       send &= (m_resource.protocol().toLower() == u.protocol().toLower());
00453       send &= (m_resource.host().toLower() == u.host().toLower());
00454 
00455       if (m_resource.port() > 0 && u.port() > 0)
00456         send &= (m_resource.port() == u.port());
00457 
00458       QString digestPath = u.directory (KUrl::AppendTrailingSlash | KUrl::ObeyTrailingSlash);
00459       if (digestPath.isEmpty())
00460         digestPath = "/";
00461 
00462       send &= (requestPath.startsWith(digestPath));
00463 
00464       if (send)
00465         break;
00466     }
00467 
00468     kDebug(7113) << "passed digest authentication credential test: " << send;
00469 
00470     if (!send) {
00471         m_isError = true;
00472         return;
00473     }
00474   }
00475 
00476   kDebug(7113) << "RESULT OF PARSING:";
00477   kDebug(7113) << "  algorithm: " << info.algorithm;
00478   kDebug(7113) << "  realm:     " << info.realm;
00479   kDebug(7113) << "  nonce:     " << info.nonce;
00480   kDebug(7113) << "  opaque:    " << opaque;
00481   kDebug(7113) << "  qop:       " << info.qop;
00482 
00483   // Calculate the response...
00484   QByteArray Response = calculateResponse(info, m_resource);
00485 
00486   QString auth = "Digest username=\"";
00487   auth += info.username;
00488 
00489   auth += "\", realm=\"";
00490   auth += info.realm;
00491   auth += "\"";
00492 
00493   auth += ", nonce=\"";
00494   auth += info.nonce;
00495 
00496   auth += "\", uri=\"";
00497   auth += m_resource.encodedPathAndQuery(KUrl::LeaveTrailingSlash, KUrl::AvoidEmptyPath);
00498 
00499   if (!info.algorithm.isEmpty()) {
00500     auth += "\", algorithm=\"";
00501     auth += info.algorithm;
00502     auth +="\"";
00503   }
00504 
00505   if ( !info.qop.isEmpty() )
00506   {
00507     auth += ", qop=\"";
00508     auth += info.qop;
00509     auth += "\", cnonce=\"";
00510     auth += info.cnonce;
00511     auth += "\", nc=";
00512     auth += info.nc;
00513   }
00514 
00515   auth += ", response=\"";
00516   auth += Response;
00517   if ( !opaque.isEmpty() )
00518   {
00519     auth += "\", opaque=\"";
00520     auth += opaque;
00521   }
00522   auth += "\"\r\n";
00523 
00524 // magic ends here
00525     // note that auth already contains \r\n
00526     m_headerFragment = auth;
00527     return;
00528 }
00529 
00530 
00531 QByteArray KHttpNtlmAuthentication::scheme() const
00532 {
00533     return "NTLM";
00534 }
00535 
00536 
00537 void KHttpNtlmAuthentication::setChallenge(const QByteArray &c, const KUrl &resource,
00538                                              const QByteArray &httpMethod)
00539 {
00540     KAbstractHttpAuthentication::setChallenge(c, resource, httpMethod);
00541     if (m_challenge.isEmpty()) {
00542         // The type 1 message we're going to send needs no credentials;
00543         // they come later in the type 3 message.
00544         m_needCredentials = false;
00545     }
00546 }
00547 
00548 
00549 void KHttpNtlmAuthentication::fillKioAuthInfo(KIO::AuthInfo *ai) const
00550 {
00551     authInfoBoilerplate(ai);
00552     // Every auth scheme is supposed to supply a realm according to the RFCs. Of course this doesn't
00553     // prevent Microsoft from not doing it... Dummy value!
00554     // we don't have the username yet which may (may!) contain a domain, so we really have no choice
00555     ai->realmValue = "NTLM";
00556 }
00557 
00558 
00559 void KHttpNtlmAuthentication::generateResponse(const QString &_user, const QString &password)
00560 {
00561     generateResponseCommon(_user, password);
00562     if (m_isError) {
00563         return;
00564     }
00565 
00566     QByteArray buf;
00567 
00568     if (m_challenge.isEmpty()) {
00569         // first, send type 1 message (with empty domain, workstation..., but it still works)
00570         m_forceDisconnect = true;
00571         KNTLM::getNegotiate(buf);
00572     } else {
00573         // we've (hopefully) received a valid type 2 message: send type 3 message as last step
00574         QString domain;
00575         QString user = m_username;
00576         if (user.contains('\\')) {
00577             domain = user.section('\\', 0, 0);
00578             user = user.section('\\', 1);
00579         }
00580 
00581         m_forceKeepAlive = true;
00582         QByteArray challenge;
00583         KCodecs::base64Decode(m_challenge[0], challenge);
00584         KNTLM::getAuth(buf, challenge, user, password, domain, QHostInfo::localHostName());
00585     }
00586 
00587     m_headerFragment = "NTLM ";
00588     m_headerFragment += KCodecs::base64Encode(buf);
00589     m_headerFragment += "\r\n";
00590 
00591     return;
00592 }
00593 
00594 
00596 #ifdef HAVE_LIBGSSAPI
00597 
00598 // just an error message formatter
00599 static QByteArray gssError(int major_status, int minor_status)
00600 {
00601     OM_uint32 new_status;
00602     OM_uint32 msg_ctx = 0;
00603     gss_buffer_desc major_string;
00604     gss_buffer_desc minor_string;
00605     OM_uint32 ret;
00606     QByteArray errorstr;
00607 
00608     do {
00609         ret = gss_display_status(&new_status, major_status, GSS_C_GSS_CODE, GSS_C_NULL_OID, &msg_ctx, &major_string);
00610         errorstr += (const char *)major_string.value;
00611         errorstr += ' ';
00612         ret = gss_display_status(&new_status, minor_status, GSS_C_MECH_CODE, GSS_C_NULL_OID, &msg_ctx, &minor_string);
00613         errorstr += (const char *)minor_string.value;
00614         errorstr += ' ';
00615     } while (!GSS_ERROR(ret) && msg_ctx != 0);
00616 
00617     return errorstr;
00618 }
00619 
00620 
00621 QByteArray KHttpNegotiateAuthentication::scheme() const
00622 {
00623     return "Negotiate";
00624 }
00625 
00626 
00627 void KHttpNegotiateAuthentication::setChallenge(const QByteArray &c, const KUrl &resource,
00628                                                 const QByteArray &httpMethod)
00629 {
00630     KAbstractHttpAuthentication::setChallenge(c, resource, httpMethod);
00631     // GSSAPI knows how to get the credentials on its own
00632     m_needCredentials = false;
00633 }
00634 
00635 
00636 void KHttpNegotiateAuthentication::fillKioAuthInfo(KIO::AuthInfo *ai) const
00637 {
00638     authInfoBoilerplate(ai);
00639     //### does GSSAPI supply anything realm-like? dummy value for now.
00640     ai->realmValue = "Negotiate";
00641 }
00642 
00643 
00644 void KHttpNegotiateAuthentication::generateResponse(const QString &user, const QString &password)
00645 {
00646     generateResponseCommon(user, password);
00647     if (m_isError) {
00648         return;
00649     }
00650 
00651     OM_uint32 major_status, minor_status;
00652     gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
00653     gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
00654     gss_name_t server;
00655     gss_ctx_id_t ctx;
00656     gss_OID mech_oid;
00657     static gss_OID_desc krb5_oid_desc = {9, (void *) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"};
00658     static gss_OID_desc spnego_oid_desc = {6, (void *) "\x2b\x06\x01\x05\x05\x02"};
00659     gss_OID_set mech_set;
00660     gss_OID tmp_oid;
00661 
00662     ctx = GSS_C_NO_CONTEXT;
00663     mech_oid = &krb5_oid_desc;
00664 
00665     // see whether we can use the SPNEGO mechanism
00666     major_status = gss_indicate_mechs(&minor_status, &mech_set);
00667     if (GSS_ERROR(major_status)) {
00668         kDebug(7113) << "gss_indicate_mechs failed: " << gssError(major_status, minor_status);
00669     } else {
00670         for (uint i = 0; i < mech_set->count; i++) {
00671             tmp_oid = &mech_set->elements[i];
00672             if (tmp_oid->length == spnego_oid_desc.length &&
00673                 !memcmp(tmp_oid->elements, spnego_oid_desc.elements, tmp_oid->length)) {
00674                 kDebug(7113) << "found SPNEGO mech";
00675                 mech_oid = &spnego_oid_desc;
00676                 break;
00677             }
00678         }
00679         gss_release_oid_set(&minor_status, &mech_set);
00680     }
00681 
00682     // the service name is "HTTP/f.q.d.n"
00683     QByteArray servicename = "HTTP@";
00684     servicename += m_resource.host().toAscii();
00685 
00686     input_token.value = (void *)servicename.data();
00687     input_token.length = servicename.length() + 1;
00688 
00689     major_status = gss_import_name(&minor_status, &input_token,
00690                                    GSS_C_NT_HOSTBASED_SERVICE, &server);
00691 
00692     input_token.value = NULL;
00693     input_token.length = 0;
00694 
00695     if (GSS_ERROR(major_status)) {
00696         kDebug(7113) << "gss_import_name failed: " << gssError(major_status, minor_status);
00697         m_isError = true;
00698         return;
00699     }
00700 
00701     OM_uint32 req_flags = 0;
00702     // GSSAPI knows how to get the credentials its own way, so don't ask for any
00703     major_status = gss_init_sec_context(&minor_status, GSS_C_NO_CREDENTIAL,
00704                                         &ctx, server, mech_oid,
00705                                         req_flags, GSS_C_INDEFINITE,
00706                                         GSS_C_NO_CHANNEL_BINDINGS,
00707                                         GSS_C_NO_BUFFER, NULL, &output_token,
00708                                         NULL, NULL);
00709 
00710     if (GSS_ERROR(major_status) || (output_token.length == 0)) {
00711         kDebug(7113) << "gss_init_sec_context failed: " << gssError(major_status, minor_status);
00712         gss_release_name(&minor_status, &server);
00713         if (ctx != GSS_C_NO_CONTEXT) {
00714             gss_delete_sec_context(&minor_status, &ctx, GSS_C_NO_BUFFER);
00715             ctx = GSS_C_NO_CONTEXT;
00716         }
00717         m_isError = true;
00718         return;
00719     }
00720 
00721     m_headerFragment = "Negotiate ";
00722     m_headerFragment += QByteArray::fromRawData((const char *)output_token.value,
00723                                                 output_token.length).toBase64();
00724     m_headerFragment += "\r\n";
00725 
00726     // free everything
00727     gss_release_name(&minor_status, &server);
00728     if (ctx != GSS_C_NO_CONTEXT) {
00729         gss_delete_sec_context(&minor_status, &ctx, GSS_C_NO_BUFFER);
00730         ctx = GSS_C_NO_CONTEXT;
00731     }
00732     gss_release_buffer(&minor_status, &output_token);
00733 }
00734 
00735 #endif // HAVE_LIBGSSAPI

KIOSlave

Skip menu "KIOSlave"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal