void ZLibrary::run(ZLApplication* aApp) { if (ZLLanguageUtil::isRTLLanguage(ZLibrary::Language())) { qApp->setLayoutDirection(Qt::RightToLeft); } QString qml(QString::fromStdString(BaseDirectory + BOOKS_QML_FILE)); HDEBUG("qml file" << qPrintable(qml)); QQuickView* view = SailfishApp::createView(); QQmlContext* root = view->rootContext(); QSize screenSize(view->screen()->size()); booksPPI = #if defined(__i386__) (screenSize == QSize(1536,2048)) ? 330 : 300; #elif defined(__arm__) (screenSize == QSize(540,960)) ? 245 : 290; #else # error Unexpected architechture #endif HDEBUG("screen" << screenSize << booksPPI << "dpi"); root->setContextProperty("PointsPerInch", booksPPI); root->setContextProperty("MaximumHintCount", 1); view->setTitle(qtTrId("books-app-name")); view->setSource(QUrl::fromLocalFile(qml)); view->show(); HDEBUG("started"); qApp->exec(); HDEBUG("exiting..."); }
ssize_t p_sock_read(int index, struct file *filp, char *buf, size_t count, loff_t *f_pos) { // context *ct=getct(index,*f_pos); pipe_file *pp=&(pipes[index]); kpipe_setup *pipeSetup=&(pipeManage.threads[index].pipeSetup[0]); size_t len; int type; loff_t tmp_pos=*f_pos; sock_pos_t *sockPos=filp->private_data; if(!filp->private_data) { HDEBUG("first read,malloc sock_pos_t\n"); sockPos=kmalloc(sizeof(sock_pos_t),GFP_KERNEL); memset(sockPos,0,sizeof(sock_pos_t)); sockPos->magic = SOCK_POS_MAGIC; filp->private_data = sockPos; } Down(index); if(tmp_pos >= ((pp->ct)[CONTEXT]).bpos) { HDEBUG("read idx\n"); if(pipeSetup->pathIndex!=INDEX_PATH_NUM) pipeSetup++; tmp_pos -=((pp->ct)[CONTEXT]).bpos; } type=pipeSetup->type; Up(index); len = p_close_createAndRead(sockPos,pipeSetup,buf,count,&tmp_pos); if(len>=0) { *f_pos +=len; sockPos->pos = tmp_pos+len; } return len; }
int BooksBookModel::Data::pickPage(const BooksPos& aPagePos, const BooksPos& aNextPagePos, int aPageCount) const { int page = 0; if (aPagePos.valid()) { if (!aNextPagePos.valid()) { // Last page stays the last page = iPageMarks.count() - 1; HDEBUG("last page" << page); } else { BooksPos::ConstIterator it = qFind(iPageMarks, aPagePos); if (it == iPageMarks.end()) { // Two 90-degrees rotations should return the reader // back to the same page. That's what this is about. const BooksPos& pos = (iPageMarks.count() > aPageCount) ? aPagePos : aNextPagePos; it = qUpperBound(iPageMarks, pos); page = (int)(it - iPageMarks.begin()); if (page > 0) page--; HDEBUG("using page" << page << "for" << pos); } else { page = it - iPageMarks.begin(); HDEBUG("found" << aPagePos << "at page" << page); } } } return page; }
int BooksBookModel::Data::pickPage(const BooksPos& aPagePos) const { int page = 0; if (aPagePos.valid()) { BooksPos::ConstIterator it = qFind(iPageMarks, aPagePos); if (it == iPageMarks.end()) { it = qUpperBound(iPageMarks, aPagePos); page = (int)(it - iPageMarks.begin()) - 1; HDEBUG("using page" << page << "for" << aPagePos); } else { page = it - iPageMarks.begin(); HDEBUG("found" << aPagePos << "at page" << page); } } return page; }
void BooksDialogManager::errorBox( const ZLResourceKey& key, const std::string& message) const { HDEBUG(QString::fromStdString(key.Name) << message.c_str()); }
static int strcut(uschar *str, uschar **ptrs, int nptrs) { uschar *last_sub_start = str; int n; for (n = 0; n < nptrs; n++) ptrs[n] = NULL; n = 1; while (*str) { if (*str == '\t') { if (n <= nptrs) { *ptrs++ = last_sub_start; last_sub_start = str + 1; *str = '\0'; } n++; } str++; } /* It's acceptable for the string to end with a tab character. We see this in AUTH PLAIN without an initial response from the client, which causing us to send "334 " and get the data from the client. */ if (n <= nptrs) { *ptrs = last_sub_start; } else { HDEBUG(D_auth) debug_printf("dovecot: warning: too many results from tab-splitting; saw %d fields, room for %d\n", n, nptrs); n = nptrs; } return n <= nptrs ? n : nptrs; }
void BooksDialogManager::informationBox( const std::string& title, const std::string& message) const { HDEBUG(QString::fromStdString(title) << message.c_str()); }
void BooksListWatcher::onWidthChanged() { HASSERT(sender() == iListView); HDEBUG(iListView->width()); // Width change will probably be followed by height change iResizeTimer->start(); }
shared_ptr<ZLDialog> BooksDialogManager::createDialog( const ZLResourceKey& aKey) const { HDEBUG(aKey.Name.c_str()); return NULL; }
shared_ptr<ZLOptionsDialog> BooksDialogManager::createOptionsDialog( const ZLResourceKey& aKey, shared_ptr<ZLRunnable> aApplyAction, bool aApplyButton) const { HDEBUG(aKey.Name.c_str()); return NULL; }
shared_ptr<ZLOpenFileDialog> BooksDialogManager::createOpenFileDialog( const ZLResourceKey& aKey, const std::string& aDirPath, const std::string& aFilePath, const ZLOpenFileDialog::Filter& aFilter) const { HDEBUG(aKey.Name.c_str()); return NULL; }
int BooksDialogManager::questionBox( const ZLResourceKey& key, const std::string& message, const ZLResourceKey& button0, const ZLResourceKey& button1, const ZLResourceKey& button2) const { HDEBUG(QString::fromStdString(key.Name) << message.c_str()); return -1; }
bool ZLibrary::init(int& aArgc, char** &aArgv) { HDEBUG("initializing"); ZLibrary::parseArguments(aArgc, aArgv); std::string rootDir("/"); Dl_info info; void* addr = NULL; if (backtrace(&addr, 1) && dladdr(addr, &info)) { // Step two levels up. For an application deployed from QtCreator // it's going to be /opt/sdk/<app-name> directory, for a normally // installed app - the root directory. HDEBUG("app path" << info.dli_fname); char* slash = (char*)strrchr(info.dli_fname, '/'); if (slash) { slash[0] = 0; HDEBUG("app dir" << info.dli_fname); slash = (char*)strrchr(info.dli_fname, '/'); if (slash) { slash[0] = 0; slash = (char*)strrchr(info.dli_fname, '/'); if (slash) { slash[1] = 0; HDEBUG("root dir" << info.dli_fname); rootDir = info.dli_fname; } } } } ((std::string&)BaseDirectory) = rootDir; ourApplicationName = BOOKS_APP_NAME; ourZLibraryDirectory = BaseDirectory + BOOKS_DATA_DIR; ourImageDirectory = BaseDirectory + BOOKS_ICONS_DIR; ourDefaultFilesPathPrefix = ourZLibraryDirectory + "/"; ourApplicationDirectory = ourZLibraryDirectory; ourApplicationImageDirectory = ourImageDirectory; ourApplicationWritableDirectory = (QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/" BOOKS_APP_NAME)).toStdString(); HDEBUG("zlibrary dir" << ourZLibraryDirectory.c_str()); HDEBUG("image dir" << ourImageDirectory.c_str()); HDEBUG("writable dir" << ourApplicationWritableDirectory.c_str()); BooksStorageManager::instance(); ZLQtTimeManager::createInstance(); ZLQtFSManager::createInstance(); BooksDialogManager::createInstance(); ZLQtImageManager::createInstance(); ZLEncodingCollection::Instance().registerProvider(new IConvEncodingConverterProvider()); ZLApplication::Instance(); ZLFile::initCache(); return true; }
void BooksListWatcher::onHeightChanged() { HASSERT(sender() == iListView); HDEBUG(iListView->height()); if (iResizeTimer->isActive()) { // Height is usually changed after width iResizeTimer->stop(); updateSize(); } else { iResizeTimer->start(); } }
void BooksCoverModel::setSource(QObject* aSrc) { QAbstractItemModel* oldM = sourceModel(); if (aSrc != oldM) { const int oldCount = count(); if (oldM) { BooksShelf* oldShelf = qobject_cast<BooksShelf*>(oldM); if (oldShelf) { const int n = oldShelf->count(); for (int i=0; i<n; i++) { onBookRemoved(oldShelf->bookAt(i)); } } oldM->disconnect(this); } if (aSrc) { QAbstractItemModel* newM = qobject_cast<QAbstractItemModel*>(aSrc); if (newM) { setSourceModel(newM); BooksShelf* newShelf = qobject_cast<BooksShelf*>(newM); if (newShelf) { const int n = newShelf->count(); for (int i=0; i<n; i++) { onBookAdded(newShelf->bookAt(i)); } connect(newShelf, SIGNAL(bookAdded(BooksBook*)), SLOT(onBookAdded(BooksBook*))); connect(newShelf, SIGNAL(bookRemoved(BooksBook*)), SLOT(onBookRemoved(BooksBook*))); } connect(newM, SIGNAL(rowsInserted(QModelIndex,int,int)), SIGNAL(countChanged())); connect(newM, SIGNAL(rowsRemoved(QModelIndex,int,int)), SIGNAL(countChanged())); connect(newM, SIGNAL(modelReset()), SIGNAL(countChanged())); } else { HDEBUG("unexpected source" << aSrc); setSourceModel(NULL); } } else { setSourceModel(NULL); } if (oldCount != count()) { Q_EMIT countChanged(); } } }
void BooksListWatcher::updateCurrentIndex() { int index = -1; if (QMetaObject::invokeMethod(iListView, LISTVIEW_INDEX_AT, Q_RETURN_ARG(int,index), Q_ARG(qreal,iContentX+width()/2), Q_ARG(qreal,iContentY+height()/2))) { if (iCurrentIndex != index) { HDEBUG(index); iCurrentIndex = index; Q_EMIT currentIndexChanged(); } } }
int auth_heimdal_gssapi_client( auth_instance *ablock, /* authenticator block */ smtp_inblock *inblock, /* connection inblock */ smtp_outblock *outblock, /* connection outblock */ int timeout, /* command timeout */ uschar *buffer, /* buffer for reading response */ int buffsize) /* size of buffer */ { HDEBUG(D_auth) debug_printf("Client side NOT IMPLEMENTED: you should not see this!\n"); /* NOT IMPLEMENTED */ return FAIL; }
void BooksListWatcher::updateSize() { const QSize size(iListView->width(), iListView->height()); HDEBUG(size); if (iSize != size) { const QSize oldSize(iSize); iSize = size; Q_EMIT sizeChanged(); if (oldSize.width() != iSize.width()) { Q_EMIT widthChanged(); } if (oldSize.height() != iSize.height()) { Q_EMIT heightChanged(); } } }
void ZLibrary::initLocale() { const char* locale = setlocale(LC_MESSAGES, ""); HDEBUG(locale); if (locale) { std::string sLocale = locale; const int dotIndex = sLocale.find('.'); if (dotIndex != -1) sLocale = sLocale.substr(0, dotIndex); const int dashIndex = std::min(sLocale.find('_'), sLocale.find('-')); if (dashIndex == -1) { ourLanguage = sLocale; } else { ourLanguage = sLocale.substr(0, dashIndex); ourCountry = sLocale.substr(dashIndex + 1); } } }
static int exim_gssapi_error_defer(uschar *store_reset_point, OM_uint32 major, OM_uint32 minor, const char *format, ...) { va_list ap; uschar buffer[STRING_SPRINTF_BUFFER_SIZE]; OM_uint32 maj_stat, min_stat; OM_uint32 msgcontext = 0; gss_buffer_desc status_string; va_start(ap, format); if (!string_vformat(buffer, sizeof(buffer), format, ap)) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "exim_gssapi_error_defer expansion larger than %lu", sizeof(buffer)); va_end(ap); auth_defer_msg = NULL; do { maj_stat = gss_display_status(&min_stat, major, GSS_C_GSS_CODE, GSS_C_NO_OID, &msgcontext, &status_string); if (auth_defer_msg == NULL) { auth_defer_msg = string_copy(US status_string.value); } HDEBUG(D_auth) debug_printf("heimdal %s: %.*s\n", buffer, (int)status_string.length, CS status_string.value); gss_release_buffer(&min_stat, &status_string); } while (msgcontext != 0); if (store_reset_point) store_reset(store_reset_point); return DEFER; }
void ZLibrary::initApplication(const std::string& aName) { HDEBUG(aName.c_str()); }
static int p_ioctl(int index, struct inode* inode, struct file* filp, unsigned int cmd, unsigned long arg) { context *ct = filp->private_data; pipe_file *pp = &(pipes[index]); tell_inf t_inf; size_inf s_inf; #ifdef KRSA krsa_arg rsa; unsigned char *input = NULL, output[MAX_RSA_MODULUS_LEN]; unsigned int inputlen = 0, outputlen = 0; #endif int err = 0, ret = 0, i; if(!capable(CAP_SYS_ADMIN)) return -EPERM; if(_IOC_TYPE(cmd) != P_IOCMAGIC) return -ENOTTY; if(_IOC_DIR(cmd) & _IOC_READ) { err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd)); } else if(_IOC_DIR(cmd) & _IOC_WRITE) { err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd)); } if(err) return -EFAULT; Down(index); switch(cmd) { case P_IOCCLEAR: dev_flush(&(pp->device)); for(i=0; i<=CONTEXT; i++) { ((pp->ct)[i]).hotp = NULL; } break; case P_IOCRESET: memset(pp->ct, 0, sizeof(context)*(CONTEXT+1)); #ifdef __PIPE_SELECT__ pp->r_poll = 1; pp->r_pos = 0; #endif for(i=0; i<=CONTEXT; i++) { ((pp->ct)[i]).r_able = 1; ((pp->ct)[i]).w_able = 1; } RELEASE(index) = 0; WRITERS(index) = 0; dev_flush(&(pp->device)); (pp->device).ctp = pp->ct; (pp->device).pred = 2*BUFF_SIZE; #ifdef KERNEL_PIPE pipeType[index]=PIPE_TYPE_USER_THREAD; #endif break; case P_IOCSIZE: if(copy_from_user((char*)&s_inf, (char*)arg, sizeof(size_inf))) { ret = (-EFAULT); goto my_error; } #ifndef CONFIG_PROC_PIPE_64_BITS_SUPPORT #ifndef CONFIG_PROC_PIPE_KERNEL_SUPPORT_64_BITS if(s_inf.mdas > 0xFFFFFFFFF || s_inf.idxs > 0xFFFFFFFF) { ret = (-EFAULT); goto my_error; } #endif (pp->mda)->size = s_inf.mdas; (pp->idx)->size = s_inf.idxs; #else // !CONFIG_PROC_PIPE_64_BITS_SUPPORT #if 0 (pp->mda)->size = s_inf.mdas; (pp->idx)->size = s_inf.idxs; #else (pp->mda)->size = 0; (pp->idx)->size = 0; #endif pp->mda_size = s_inf.mdas; pp->idx_size = s_inf.idxs; #endif // !CONFIG_PROC_PIPE_64_BITS_SUPPORT for(i=0; i<CONTEXT; i++) { ((pp->ct)[i]).epos = s_inf.mdas; } ((pp->ct)[CONTEXT]).bpos = s_inf.dats; ((pp->ct)[CONTEXT]).epos = s_inf.dats + s_inf.idxs; ((pp->ct)[CONTEXT]).seek = s_inf.dats; break; case P_IOCREVS: ((pp->ct)[CONTEXT]).reverse = *((int*)arg); break; case P_IOCTELL: t_inf.seek = filp->f_pos; t_inf.size = (BPOS(ct))?(BUFF_SIZE):(SIZE(ct)); if(copy_to_user((char*)arg, (char*)&t_inf, sizeof(tell_inf))) { ret = (-EFAULT); goto my_error; } break; case P_IOCRELS: RELEASE(index) = 1; wake_up_interruptible(&(RQ(index))); wake_up_interruptible(&(WQ(index))); break; case P_IOCPRED: (pp->device).pred = *((size_t*)arg); break; #ifdef KRSA case P_IOCKRSA: if(copy_from_user((char*)&rsa, (char*)arg, sizeof(krsa_arg))) { ret = (-EFAULT); goto my_error; } if(!access_ok(VERIFY_READ, (void *)(rsa.len), sizeof(unsigned int))) { ret = (-EFAULT); goto my_error; } if(copy_from_user((char*)&inputlen, (char*)(rsa.len), sizeof(unsigned int))) { ret = (-EFAULT); goto my_error; } if(!(input = kmalloc(inputlen, GFP_KERNEL))) { ret = (-EFAULT); goto my_error; } if(!access_ok(VERIFY_READ, (void *)(rsa.buf), inputlen)) { ret = (-EFAULT); goto my_error; } if(copy_from_user((char*)input, (char*)(rsa.buf), inputlen)) { ret = (-EFAULT); goto my_error; } if(RSAPrivateBlock(output, &outputlen, input, inputlen, &(rsa.key))) { ret = (-EFAULT); goto my_error; } if(!access_ok(VERIFY_WRITE, (void *)(rsa.buf), outputlen)) { ret = (-EFAULT); goto my_error; } if(copy_to_user((char*)(rsa.buf), (char*)output, outputlen)) { ret = (-EFAULT); goto my_error; } if(!access_ok(VERIFY_WRITE, (void *)(rsa.len), sizeof(unsigned int))) { ret = (-EFAULT); goto my_error; } if(copy_to_user((char*)(rsa.len), (char*)&outputlen, sizeof(unsigned int))) { ret = (-EFAULT); goto my_error; } break; #endif #ifdef KERNEL_PIPE case P_IOCPIPETYPE: { int val; get_user(val,(int *)arg); if(val<0) { ret= -EFAULT; break; } #ifdef NO_KERNEL_PIPE_THREAD if(val<=PIPE_TYPE_KERNEL_DIRECT) #else if(val<=PIPE_TYPE_KERNEL_THREAD) #endif pipeType[index]=val; else ret= -EFAULT; } break; case P_IOCPIPESTART: { // int len; kpipe_setup userPath; kpipe_setup *pipeSetup; pipe_thread *pipeThread; DECLARE_WAIT_QUEUE_HEAD(WQ); copy_from_user(&userPath,(kpipe_setup *)arg,sizeof(kpipe_setup)); pipeSetup=pipeManage.threads[index].pipeSetup; pipeThread=&(pipeManage.threads[index]); //select a default pipe type. if(pipeType[index]==PIPE_TYPE_USER_THREAD) pipeType[index]=defaultPipeType; if(pipeType[index]!=PIPE_TYPE_KERNEL_THREAD && pipeType[index]!=PIPE_TYPE_KERNEL_DIRECT) pipeType[index]=PIPE_TYPE_KERNEL_DIRECT; //pipe_type_kernel_direct doesn't support local file. #ifdef NO_KERNEL_PIPE_THREAD if(pipeType[index]==PIPE_TYPE_KERNEL_DIRECT) { if(userPath.type>PIPE_KP) { ret = -EFAULT; break; } } #endif if(*(pipeSetup->host)) //if it has used already? a.dma or a.index. pipeSetup++; if(*(pipeSetup->host)) { HDEBUG("no pipeSetup\n"); ret = -EFAULT; break; } pipeThread->index = index; //a or b. pipeSetup->index = index; // copy_from_user(&pipeSetup->nums,&userPath.nums,1); pipeSetup->nums = userPath.nums; // copy_from_user(&pipeSetup->size,&((kpipe_setup *)arg)->size,sizeof(int)); pipeSetup->size = userPath.size; // copy_from_user(&httpThread->type,&((kpipe_setup *)arg)->type,1); pipeThread->type = userPath.type; //close or keep alive. memcpy(pipeSetup->host,userPath.host,16); memcpy(pipeSetup->procfile,userPath.procfile,16); if(!strcmp(pipeSetup->procfile+strlen("/proc/a."),"mda")) { pipeSetup->pathIndex = MEDIA_PATH_NUM; //dma or index. } else { pipeSetup->pathIndex = INDEX_PATH_NUM; } // pipeSetup->host=HTTP_MALLOC(strlen(userPath->host)+1); pipeSetup->path=HTTP_MALLOC(userPath.pathSize); // pipeSetup->sessionid=HTTP_MALLOC(((kpipe_setup *)arg)->sessionidSize); if(!pipeSetup->path) { // no memroy. } copy_from_user(pipeSetup->path,userPath.path,userPath.pathSize); if(userPath.sessionid){ pipeSetup->sessionid=HTTP_MALLOC(userPath.sessionidSize); copy_from_user(pipeSetup->sessionid,userPath.sessionid,userPath.sessionidSize); } // copy_from_user(&(pipeSetup->port),&userPath.port),sizeof(short)); pipeSetup->port = userPath.port; // copy_from_user(&(pipeSetup->protection),&(((kpipe_setup *)arg)->protection),sizeof(int)); pipeSetup->protection = userPath.protection; HDEBUG("ioctl:%s %d:%s\n",pipeSetup->host,pipeSetup->port,pipeSetup->path); //pipeManage.starts[index][pipeSetup->index].start=1; if(pipeType[index]==PIPE_TYPE_KERNEL_THREAD) { down_interruptible(&(pipeManage.semaphore)); atomic_set(&(pipeManage.starts[index][pipeSetup->pathIndex]),1); //start kernel_thread. //to wakeup manage thread. while(pipeManage.change) { interruptible_sleep_on_timeout(&WQ,5); } pipeManage.change=1; up(&(pipeManage.semaphore)); wake_up_interruptible(&(pipeManage.wq)); } } break; case P_IOCPIPESTOP: { pipe_thread *thread=&(pipeManage.threads[index]); int i; DECLARE_WAIT_QUEUE_HEAD(WQ); RELEASE(index) = 1; if(pipeType[index]==PIPE_TYPE_KERNEL_THREAD) { wake_up_interruptible(&(RQ(index))); wake_up_interruptible(&(WQ(index))); down_interruptible(&(pipeManage.semaphore)); atomic_set(&(pipeManage.stops[index]),1); //to wakeup manage thread. while(pipeManage.change) { interruptible_sleep_on_timeout(&WQ,5); } pipeManage.change = 1; up(&(pipeManage.semaphore)); wake_up_interruptible(&(pipeManage.wq)); } else { for(i=0;i<END_PATH_NUM;i++) { if(thread->pipeSetup[i].path) { HTTP_FREE(thread->pipeSetup[i].path); if(thread->pipeSetup[i].sessionid) HTTP_FREE(thread->pipeSetup[i].sessionid); memset(&(thread->pipeSetup[i]),0,sizeof(kpipe_setup)); } } } } break; #endif default: ret = (-ENOTTY); } my_error: #ifdef KRSA if(input) kfree(input); #endif Up(index); return ret; }
int auth_cyrus_sasl_server(auth_instance *ablock, uschar *data) { auth_cyrus_sasl_options_block *ob = (auth_cyrus_sasl_options_block *)(ablock->options_block); uschar *output, *out2, *input, *clear, *hname; uschar *debug = NULL; /* Stops compiler complaining */ sasl_callback_t cbs[] = {{SASL_CB_LIST_END, NULL, NULL}}; sasl_conn_t *conn; char * realm_expanded = NULL; int rc, firsttime = 1, clen, *negotiated_ssf_ptr = NULL, negotiated_ssf; unsigned int inlen, outlen; input = data; inlen = Ustrlen(data); HDEBUG(D_auth) debug = string_copy(data); hname = expand_string(ob->server_hostname); if (hname && ob->server_realm) realm_expanded = CS expand_string(ob->server_realm); if (!hname || !realm_expanded && ob->server_realm) { auth_defer_msg = expand_string_message; return DEFER; } if (inlen) { if ((clen = b64decode(input, &clear)) < 0) return BAD64; input = clear; inlen = clen; } if ((rc = sasl_server_init(cbs, "exim")) != SASL_OK) { auth_defer_msg = US"couldn't initialise Cyrus SASL library"; return DEFER; } rc = sasl_server_new(CS ob->server_service, CS hname, realm_expanded, NULL, NULL, NULL, 0, &conn); HDEBUG(D_auth) debug_printf("Initialised Cyrus SASL server connection; service=\"%s\" fqdn=\"%s\" realm=\"%s\"\n", ob->server_service, hname, realm_expanded); if (rc != SASL_OK ) { auth_defer_msg = US"couldn't initialise Cyrus SASL connection"; sasl_done(); return DEFER; } if (tls_in.cipher) { if ((rc = sasl_setprop(conn, SASL_SSF_EXTERNAL, (sasl_ssf_t *) &tls_in.bits)) != SASL_OK) { HDEBUG(D_auth) debug_printf("Cyrus SASL EXTERNAL SSF set %d failed: %s\n", tls_in.bits, sasl_errstring(rc, NULL, NULL)); auth_defer_msg = US"couldn't set Cyrus SASL EXTERNAL SSF"; sasl_done(); return DEFER; } else HDEBUG(D_auth) debug_printf("Cyrus SASL set EXTERNAL SSF to %d\n", tls_in.bits); } else HDEBUG(D_auth) debug_printf("Cyrus SASL: no TLS, no EXTERNAL SSF set\n"); /* So sasl_setprop() documents non-shorted IPv6 addresses which is incredibly annoying; looking at cyrus-imapd-2.3.x source, the IP address is constructed with their iptostring() function, which just wraps getnameinfo(..., NI_NUMERICHOST|NI_NUMERICSERV), which is equivalent to the inet_ntop which we wrap in our host_ntoa() function. So the docs are too strict and we shouldn't worry about :: contractions. */ /* Set properties for remote and local host-ip;port */ for (int i = 0; i < 2; ++i) { struct sockaddr_storage ss; int (*query)(int, struct sockaddr *, socklen_t *); int propnum, port; const uschar *label; uschar *address, *address_port; const char *s_err; socklen_t sslen; if (i) { query = &getpeername; propnum = SASL_IPREMOTEPORT; label = CUS"peer"; } else { query = &getsockname; propnum = SASL_IPLOCALPORT; label = CUS"local"; } sslen = sizeof(ss); if ((rc = query(fileno(smtp_in), (struct sockaddr *) &ss, &sslen)) < 0) { HDEBUG(D_auth) debug_printf("Failed to get %s address information: %s\n", label, strerror(errno)); break; } address = host_ntoa(-1, &ss, NULL, &port); address_port = string_sprintf("%s;%d", address, port); if ((rc = sasl_setprop(conn, propnum, address_port)) != SASL_OK) { s_err = sasl_errdetail(conn); HDEBUG(D_auth) debug_printf("Failed to set %s SASL property: [%d] %s\n", label, rc, s_err ? s_err : "<unknown reason>"); break; } HDEBUG(D_auth) debug_printf("Cyrus SASL set %s hostport to: %s\n", label, address_port); } for (rc = SASL_CONTINUE; rc == SASL_CONTINUE; ) { if (firsttime) { firsttime = 0; HDEBUG(D_auth) debug_printf("Calling sasl_server_start(%s,\"%s\")\n", ob->server_mech, debug); rc = sasl_server_start(conn, CS ob->server_mech, inlen?CS input:NULL, inlen, (const char **)(&output), &outlen); } else { /* make sure that we have a null-terminated string */ out2 = string_copyn(output, outlen); if ((rc = auth_get_data(&input, out2, outlen)) != OK) { /* we couldn't get the data, so free up the library before * returning whatever error we get */ sasl_dispose(&conn); sasl_done(); return rc; } inlen = Ustrlen(input); HDEBUG(D_auth) debug = string_copy(input); if (inlen) { if ((clen = b64decode(input, &clear)) < 0) { sasl_dispose(&conn); sasl_done(); return BAD64; } input = clear; inlen = clen; } HDEBUG(D_auth) debug_printf("Calling sasl_server_step(\"%s\")\n", debug); rc = sasl_server_step(conn, CS input, inlen, (const char **)(&output), &outlen); } if (rc == SASL_BADPROT) { sasl_dispose(&conn); sasl_done(); return UNEXPECTED; } if (rc == SASL_CONTINUE) continue; /* Get the username and copy it into $auth1 and $1. The former is now the preferred variable; the latter is the original variable. */ if ((sasl_getprop(conn, SASL_USERNAME, (const void **)(&out2))) != SASL_OK) { HDEBUG(D_auth) debug_printf("Cyrus SASL library will not tell us the username: %s\n", sasl_errstring(rc, NULL, NULL)); log_write(0, LOG_REJECT, "%s authenticator (%s):\n " "Cyrus SASL username fetch problem: %s", ablock->name, ob->server_mech, sasl_errstring(rc, NULL, NULL)); sasl_dispose(&conn); sasl_done(); return FAIL; } auth_vars[0] = expand_nstring[1] = string_copy(out2); expand_nlength[1] = Ustrlen(out2); expand_nmax = 1; switch (rc) { case SASL_FAIL: case SASL_BUFOVER: case SASL_BADMAC: case SASL_BADAUTH: case SASL_NOAUTHZ: case SASL_ENCRYPT: case SASL_EXPIRED: case SASL_DISABLED: case SASL_NOUSER: /* these are considered permanent failure codes */ HDEBUG(D_auth) debug_printf("Cyrus SASL permanent failure %d (%s)\n", rc, sasl_errstring(rc, NULL, NULL)); log_write(0, LOG_REJECT, "%s authenticator (%s):\n " "Cyrus SASL permanent failure: %s", ablock->name, ob->server_mech, sasl_errstring(rc, NULL, NULL)); sasl_dispose(&conn); sasl_done(); return FAIL; case SASL_NOMECH: /* this is a temporary failure, because the mechanism is not * available for this user. If it wasn't available at all, we * shouldn't have got here in the first place... */ HDEBUG(D_auth) debug_printf("Cyrus SASL temporary failure %d (%s)\n", rc, sasl_errstring(rc, NULL, NULL)); auth_defer_msg = string_sprintf("Cyrus SASL: mechanism %s not available", ob->server_mech); sasl_dispose(&conn); sasl_done(); return DEFER; case SASL_OK: HDEBUG(D_auth) debug_printf("Cyrus SASL %s authentication succeeded for %s\n", ob->server_mech, auth_vars[0]); if ((rc = sasl_getprop(conn, SASL_SSF, (const void **)(&negotiated_ssf_ptr)))!= SASL_OK) { HDEBUG(D_auth) debug_printf("Cyrus SASL library will not tell us the SSF: %s\n", sasl_errstring(rc, NULL, NULL)); log_write(0, LOG_REJECT, "%s authenticator (%s):\n " "Cyrus SASL SSF value not available: %s", ablock->name, ob->server_mech, sasl_errstring(rc, NULL, NULL)); sasl_dispose(&conn); sasl_done(); return FAIL; } negotiated_ssf = *negotiated_ssf_ptr; HDEBUG(D_auth) debug_printf("Cyrus SASL %s negotiated SSF: %d\n", ob->server_mech, negotiated_ssf); if (negotiated_ssf > 0) { HDEBUG(D_auth) debug_printf("Exim does not implement SASL wrapping (needed for SSF %d).\n", negotiated_ssf); log_write(0, LOG_REJECT, "%s authenticator (%s):\n " "Cyrus SASL SSF %d not supported by Exim", ablock->name, ob->server_mech, negotiated_ssf); sasl_dispose(&conn); sasl_done(); return FAIL; } /* close down the connection, freeing up library's memory */ sasl_dispose(&conn); sasl_done(); /* Expand server_condition as an authorization check */ return auth_check_serv_cond(ablock); default: /* Anything else is a temporary failure, and we'll let SASL print out * the error string for us */ HDEBUG(D_auth) debug_printf("Cyrus SASL temporary failure %d (%s)\n", rc, sasl_errstring(rc, NULL, NULL)); auth_defer_msg = string_sprintf("Cyrus SASL: %s", sasl_errstring(rc, NULL, NULL)); sasl_dispose(&conn); sasl_done(); return DEFER; } } /* NOTREACHED */ return 0; /* Stop compiler complaints */ }
void auth_cyrus_sasl_init(auth_instance *ablock) { auth_cyrus_sasl_options_block *ob = (auth_cyrus_sasl_options_block *)(ablock->options_block); const uschar *list, *listptr, *buffer; int rc, i; unsigned int len; uschar *rs_point, *expanded_hostname; char *realm_expanded; sasl_conn_t *conn; sasl_callback_t cbs[] = { {SASL_CB_GETOPT, NULL, NULL }, {SASL_CB_LIST_END, NULL, NULL}}; /* default the mechanism to our "public name" */ if (ob->server_mech == NULL) ob->server_mech = string_copy(ablock->public_name); expanded_hostname = expand_string(ob->server_hostname); if (expanded_hostname == NULL) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: " "couldn't expand server_hostname [%s]: %s", ablock->name, ob->server_hostname, expand_string_message); realm_expanded = NULL; if (ob->server_realm != NULL) { realm_expanded = CS expand_string(ob->server_realm); if (realm_expanded == NULL) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: " "couldn't expand server_realm [%s]: %s", ablock->name, ob->server_realm, expand_string_message); } /* we're going to initialise the library to check that there is an * authenticator of type whatever mechanism we're using */ cbs[0].proc = (int(*)(void)) &mysasl_config; cbs[0].context = ob->server_mech; if ((rc = sasl_server_init(cbs, "exim")) != SASL_OK ) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: " "couldn't initialise Cyrus SASL library.", ablock->name); if ((rc = sasl_server_new(CS ob->server_service, CS expanded_hostname, realm_expanded, NULL, NULL, NULL, 0, &conn)) != SASL_OK ) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: " "couldn't initialise Cyrus SASL server connection.", ablock->name); if ((rc = sasl_listmech(conn, NULL, "", ":", "", (const char **)&list, &len, &i)) != SASL_OK ) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: " "couldn't get Cyrus SASL mechanism list.", ablock->name); i = ':'; listptr = list; HDEBUG(D_auth) { debug_printf("Initialised Cyrus SASL service=\"%s\" fqdn=\"%s\" realm=\"%s\"\n", ob->server_service, expanded_hostname, realm_expanded); debug_printf("Cyrus SASL knows mechanisms: %s\n", list); } /* the store_get / store_reset mechanism is hierarchical * the hierarchy is stored for us behind our back. This point * creates a hierarchy point for this function. */ rs_point = store_get(0); /* loop until either we get to the end of the list, or we match the * public name of this authenticator */ while ( ( buffer = string_nextinlist(&listptr, &i, NULL, 0) ) && strcmpic(buffer,ob->server_mech) ); if (!buffer) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: " "Cyrus SASL doesn't know about mechanism %s.", ablock->name, ob->server_mech); store_reset(rs_point); HDEBUG(D_auth) debug_printf("Cyrus SASL driver %s: %s initialised\n", ablock->name, ablock->public_name); /* make sure that if we get here then we're allowed to advertise. */ ablock->server = TRUE; sasl_dispose(&conn); sasl_done(); }
int auth_dovecot_server(auth_instance * ablock, uschar * data) { auth_dovecot_options_block *ob = (auth_dovecot_options_block *) ablock->options_block; struct sockaddr_un sa; uschar buffer[DOVECOT_AUTH_MAXLINELEN]; uschar *args[DOVECOT_AUTH_MAXFIELDCOUNT]; uschar *auth_command; uschar *auth_extra_data = US""; uschar *p; int nargs, tmp; int crequid = 1, cont = 1, fd = -1, ret = DEFER; BOOL found = FALSE, have_mech_line = FALSE; HDEBUG(D_auth) debug_printf("dovecot authentication\n"); if (!data) { ret = FAIL; goto out; } memset(&sa, 0, sizeof(sa)); sa.sun_family = AF_UNIX; /* This was the original code here: it is nonsense because strncpy() does not return an integer. I have converted this to use the function that formats and checks length. PH */ /* if (strncpy(sa.sun_path, ob->server_socket, sizeof(sa.sun_path)) < 0) { } */ if (!string_format(US sa.sun_path, sizeof(sa.sun_path), "%s", ob->server_socket)) { auth_defer_msg = US"authentication socket path too long"; return DEFER; } auth_defer_msg = US"authentication socket connection error"; if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) return DEFER; if (connect(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) goto out; auth_defer_msg = US"authentication socket protocol error"; socket_buffer_left = 0; /* Global, used to read more than a line but return by line */ while (cont) { if (dc_gets(buffer, sizeof(buffer), fd) == NULL) OUT("authentication socket read error or premature eof"); p = buffer + Ustrlen(buffer) - 1; if (*p != '\n') OUT("authentication socket protocol line too long"); *p = '\0'; HDEBUG(D_auth) debug_printf("received: %s\n", buffer); nargs = strcut(buffer, args, sizeof(args) / sizeof(args[0])); /* HDEBUG(D_auth) debug_strcut(args, nargs, sizeof(args) / sizeof(args[0])); */ /* Code below rewritten by Kirill Miazine ([email protected]). Only check commands that Exim will need. Original code also failed if Dovecot server sent unknown command. E.g. COOKIE in version 1.1 of the protocol would cause troubles. */ /* pdp: note that CUID is a per-connection identifier sent by the server, which increments at server discretion. By contrast, the "id" field of the protocol is a connection-specific request identifier, which needs to be unique per request from the client and is not connected to the CUID value, so we ignore CUID from server. It's purely for diagnostics. */ if (Ustrcmp(args[0], US"VERSION") == 0) { CHECK_COMMAND("VERSION", 2, 2); if (Uatoi(args[1]) != VERSION_MAJOR) OUT("authentication socket protocol version mismatch"); } else if (Ustrcmp(args[0], US"MECH") == 0) { CHECK_COMMAND("MECH", 1, INT_MAX); have_mech_line = TRUE; if (strcmpic(US args[1], ablock->public_name) == 0) found = TRUE; } else if (Ustrcmp(args[0], US"SPID") == 0) { /* Unfortunately the auth protocol handshake wasn't designed well to differentiate between auth-client/userdb/master. auth-userdb and auth-master send VERSION + SPID lines only and nothing afterwards, while auth-client sends VERSION + MECH + SPID + CUID + more. The simplest way that we can determine if we've connected to the correct socket is to see if MECH line exists or not (alternatively we'd have to have a small timeout after SPID to see if CUID is sent or not). */ if (!have_mech_line) OUT("authentication socket type mismatch" " (connected to auth-master instead of auth-client)"); } else if (Ustrcmp(args[0], US"DONE") == 0) { CHECK_COMMAND("DONE", 0, 0); cont = 0; } } if (!found) { auth_defer_msg = string_sprintf( "Dovecot did not advertise mechanism \"%s\" to us", ablock->public_name); goto out; } /* Added by PH: data must not contain tab (as it is b64 it shouldn't, but check for safety). */ if (Ustrchr(data, '\t') != NULL) { ret = FAIL; goto out; } /* Added by PH: extra fields when TLS is in use or if the TCP/IP connection is local. */ if (tls_in.cipher != NULL) auth_extra_data = string_sprintf("secured\t%s%s", tls_in.certificate_verified? "valid-client-cert" : "", tls_in.certificate_verified? "\t" : ""); else if ( interface_address != NULL && Ustrcmp(sender_host_address, interface_address) == 0) auth_extra_data = US"secured\t"; /**************************************************************************** The code below was the original code here. It didn't work. A reading of the file auth-protocol.txt.gz that came with Dovecot 1.0_beta8 indicated that this was not right. Maybe something changed. I changed it to move the service indication into the AUTH command, and it seems to be better. PH fprintf(f, "VERSION\t%d\t%d\r\nSERVICE\tSMTP\r\nCPID\t%d\r\n" "AUTH\t%d\t%s\trip=%s\tlip=%s\tresp=%s\r\n", VERSION_MAJOR, VERSION_MINOR, getpid(), cuid, ablock->public_name, sender_host_address, interface_address, data ? CS data : ""); Subsequently, the command was modified to add "secured" and "valid-client- cert" when relevant. ****************************************************************************/ auth_command = string_sprintf("VERSION\t%d\t%d\nCPID\t%d\n" "AUTH\t%d\t%s\tservice=smtp\t%srip=%s\tlip=%s\tnologin\tresp=%s\n", VERSION_MAJOR, VERSION_MINOR, getpid(), crequid, ablock->public_name, auth_extra_data, sender_host_address, interface_address, data); if (write(fd, auth_command, Ustrlen(auth_command)) < 0) HDEBUG(D_auth) debug_printf("error sending auth_command: %s\n", strerror(errno)); HDEBUG(D_auth) debug_printf("sent: %s", auth_command); while (1) { uschar *temp; uschar *auth_id_pre = NULL; int i; if (dc_gets(buffer, sizeof(buffer), fd) == NULL) { auth_defer_msg = US"authentication socket read error or premature eof"; goto out; } buffer[Ustrlen(buffer) - 1] = 0; HDEBUG(D_auth) debug_printf("received: %s\n", buffer); nargs = strcut(buffer, args, sizeof(args) / sizeof(args[0])); if (Uatoi(args[1]) != crequid) OUT("authentication socket connection id mismatch"); switch (toupper(*args[0])) { case 'C': CHECK_COMMAND("CONT", 1, 2); if ((tmp = auth_get_no64_data(&data, US args[2])) != OK) { ret = tmp; goto out; } /* Added by PH: data must not contain tab (as it is b64 it shouldn't, but check for safety). */ if (Ustrchr(data, '\t') != NULL) { ret = FAIL; goto out; } temp = string_sprintf("CONT\t%d\t%s\n", crequid, data); if (write(fd, temp, Ustrlen(temp)) < 0) OUT("authentication socket write error"); break; case 'F': CHECK_COMMAND("FAIL", 1, -1); for (i=2; (i<nargs) && (auth_id_pre == NULL); i++) { if ( Ustrncmp(args[i], US"user="******"OK", 2, -1); /* Search for the "user=$USER" string in the args array and return the proper value. */ for (i=2; (i<nargs) && (auth_id_pre == NULL); i++) { if ( Ustrncmp(args[i], US"user="******"authentication socket protocol error, username missing"); ret = OK; /* fallthrough */ default: goto out; } } out: /* close the socket used by dovecot */ if (fd >= 0) close(fd); /* Expand server_condition as an authorization check */ return ret == OK ? auth_check_serv_cond(ablock) : ret; }
int auth_cyrus_sasl_server(auth_instance *ablock, uschar *data) { auth_cyrus_sasl_options_block *ob = (auth_cyrus_sasl_options_block *)(ablock->options_block); uschar *output, *out2, *input, *clear, *hname; uschar *debug = NULL; /* Stops compiler complaining */ sasl_callback_t cbs[]={{SASL_CB_LIST_END, NULL, NULL}}; sasl_conn_t *conn; int rc, firsttime=1, clen; unsigned int inlen, outlen; input=data; inlen=Ustrlen(data); HDEBUG(D_auth) debug=string_copy(data); hname=expand_string(ob->server_hostname); if(hname == NULL) { auth_defer_msg = expand_string_message; return DEFER; } if(inlen) { clen=auth_b64decode(input, &clear); if(clen < 0) { return BAD64; } input=clear; inlen=clen; } rc=sasl_server_init(cbs, "exim"); if (rc != SASL_OK) { auth_defer_msg = US"couldn't initialise Cyrus SASL library"; return DEFER; } rc=sasl_server_new(CS ob->server_service, CS hname, CS ob->server_realm, NULL, NULL, NULL, 0, &conn); if( rc != SASL_OK ) { auth_defer_msg = US"couldn't initialise Cyrus SASL connection"; sasl_done(); return DEFER; } rc=SASL_CONTINUE; while(rc==SASL_CONTINUE) { if(firsttime) { firsttime=0; HDEBUG(D_auth) debug_printf("Calling sasl_server_start(%s,\"%s\")\n", ob->server_mech, debug); rc=sasl_server_start(conn, CS ob->server_mech, inlen?CS input:NULL, inlen, (const char **)(&output), &outlen); } else { /* make sure that we have a null-terminated string */ out2=store_get(outlen+1); memcpy(out2,output,outlen); out2[outlen]='\0'; if((rc=auth_get_data(&input, out2, outlen))!=OK) { /* we couldn't get the data, so free up the library before * returning whatever error we get */ sasl_dispose(&conn); sasl_done(); return rc; } inlen=Ustrlen(input); HDEBUG(D_auth) debug=string_copy(input); if(inlen) { clen=auth_b64decode(input, &clear); if(clen < 0) { sasl_dispose(&conn); sasl_done(); return BAD64; } input=clear; inlen=clen; } HDEBUG(D_auth) debug_printf("Calling sasl_server_step(\"%s\")\n", debug); rc=sasl_server_step(conn, CS input, inlen, (const char **)(&output), &outlen); } if(rc==SASL_BADPROT) { sasl_dispose(&conn); sasl_done(); return UNEXPECTED; } else if( rc==SASL_FAIL || rc==SASL_BUFOVER || rc==SASL_BADMAC || rc==SASL_BADAUTH || rc==SASL_NOAUTHZ || rc==SASL_ENCRYPT || rc==SASL_EXPIRED || rc==SASL_DISABLED || rc==SASL_NOUSER ) { /* these are considered permanent failure codes */ HDEBUG(D_auth) debug_printf("Cyrus SASL permanent failure %d (%s)\n", rc, sasl_errstring(rc, NULL, NULL)); log_write(0, LOG_REJECT, "%s authenticator (%s):\n " "Cyrus SASL permanent failure: %s", ablock->name, ob->server_mech, sasl_errstring(rc, NULL, NULL)); sasl_dispose(&conn); sasl_done(); return FAIL; } else if(rc==SASL_NOMECH) { /* this is a temporary failure, because the mechanism is not * available for this user. If it wasn't available at all, we * shouldn't have got here in the first place... */ HDEBUG(D_auth) debug_printf("Cyrus SASL temporary failure %d (%s)\n", rc, sasl_errstring(rc, NULL, NULL)); auth_defer_msg = string_sprintf("Cyrus SASL: mechanism %s not available", ob->server_mech); sasl_dispose(&conn); sasl_done(); return DEFER; } else if(!(rc==SASL_OK || rc==SASL_CONTINUE)) { /* Anything else is a temporary failure, and we'll let SASL print out * the error string for us */ HDEBUG(D_auth) debug_printf("Cyrus SASL temporary failure %d (%s)\n", rc, sasl_errstring(rc, NULL, NULL)); auth_defer_msg = string_sprintf("Cyrus SASL: %s", sasl_errstring(rc, NULL, NULL)); sasl_dispose(&conn); sasl_done(); return DEFER; } else if(rc==SASL_OK) { /* Get the username and copy it into $auth1 and $1. The former is now the preferred variable; the latter is the original variable. */ rc = sasl_getprop(conn, SASL_USERNAME, (const void **)(&out2)); auth_vars[0] = expand_nstring[1] = string_copy(out2); expand_nlength[1] = Ustrlen(expand_nstring[1]); expand_nmax = 1; HDEBUG(D_auth) debug_printf("Cyrus SASL %s authentication succeeded for %s\n", ob->server_mech, out2); /* close down the connection, freeing up library's memory */ sasl_dispose(&conn); sasl_done(); /* Expand server_condition as an authorization check */ return auth_check_serv_cond(ablock); } } /* NOTREACHED */ return 0; /* Stop compiler complaints */ }
QImage HarbourQrCodeImageProvider::requestImage(const QString& aId, QSize* aSize, const QSize&) { // Default background and foreground QColor background(Qt::transparent), color(Qt::black); // Parse parameters QString base32; const int sep = aId.indexOf('?'); if (sep < 0) { base32 = aId; } else { base32 = aId.left(sep); const QStringList params(aId.mid(sep + 1).split('&', QString::SkipEmptyParts)); const int n = params.count(); for (int i = 0; i < n; i++) { const QString param(params.at(i)); const int eq = param.indexOf('='); if (eq > 0) { static const QString BACKGROUND("background"); static const QString COLOR("color"); const QString name(param.left(eq).trimmed()); const QString value(param.mid(eq + 1).trimmed()); if (name == COLOR) { const QColor colorValue(value); if (colorValue.isValid()) { color = colorValue; } else { HDEBUG("Invalid" << qPrintable(name) << value); } } else if (name == BACKGROUND) { const QColor colorValue(value); if (colorValue.isValid()) { background = colorValue; } else { HDEBUG("Invalid" << qPrintable(name) << value); } } else { HDEBUG("Invalid parameter name" << name); } } else { HDEBUG("Invalid parameter" << param); } } } // Decode BASE32 const QByteArray bits(HarbourBase32::fromBase32(base32.toLocal8Bit())); QImage img; HDEBUG(base32 << "=>" << bits.size() << "bytes"); if (bits.size() > 0) { // Bits are packed, rows are rounded at byte boundary int rows, rowSize; for (rows = 2; ((rowSize = (rows + 7)/8) * rows) < bits.size(); rows++); if ((rows * rowSize) == bits.size()) { HDEBUG(rows << "x" << rows); img = QImage(rows, rows, QImage::Format_Mono); QVector<QRgb> colors; colors.append(background.rgba()); colors.append(color.rgba()); img.setColorTable(colors); for (int y = 0; y < rows; y++) { memcpy(img.scanLine(y), bits.constData() + y * rowSize, rowSize); } } } if (!img.isNull() && aSize) { *aSize = img.size(); } return img; }
int auth_heimdal_gssapi_server(auth_instance *ablock, uschar *initial_data) { gss_name_t gclient = GSS_C_NO_NAME; gss_name_t gserver = GSS_C_NO_NAME; gss_cred_id_t gcred = GSS_C_NO_CREDENTIAL; gss_ctx_id_t gcontext = GSS_C_NO_CONTEXT; uschar *ex_server_str; gss_buffer_desc gbufdesc = GSS_C_EMPTY_BUFFER; gss_buffer_desc gbufdesc_in = GSS_C_EMPTY_BUFFER; gss_buffer_desc gbufdesc_out = GSS_C_EMPTY_BUFFER; gss_OID mech_type; OM_uint32 maj_stat, min_stat; int step, error_out, i; uschar *tmp1, *tmp2, *from_client; auth_heimdal_gssapi_options_block *ob = (auth_heimdal_gssapi_options_block *)(ablock->options_block); BOOL handled_empty_ir; uschar *store_reset_point; uschar *keytab; uschar sasl_config[4]; uschar requested_qop; store_reset_point = store_get(0); HDEBUG(D_auth) debug_printf("heimdal: initialising auth context for %s\n", ablock->name); /* Construct our gss_name_t gserver describing ourselves */ tmp1 = expand_string(ob->server_service); tmp2 = expand_string(ob->server_hostname); ex_server_str = string_sprintf("%s@%s", tmp1, tmp2); gbufdesc.value = (void *) ex_server_str; gbufdesc.length = Ustrlen(ex_server_str); maj_stat = gss_import_name(&min_stat, &gbufdesc, GSS_C_NT_HOSTBASED_SERVICE, &gserver); if (GSS_ERROR(maj_stat)) return exim_gssapi_error_defer(store_reset_point, maj_stat, min_stat, "gss_import_name(%s)", CS gbufdesc.value); /* Use a specific keytab, if specified */ if (ob->server_keytab) { keytab = expand_string(ob->server_keytab); maj_stat = gsskrb5_register_acceptor_identity(CCS keytab); if (GSS_ERROR(maj_stat)) return exim_gssapi_error_defer(store_reset_point, maj_stat, min_stat, "registering keytab \"%s\"", keytab); HDEBUG(D_auth) debug_printf("heimdal: using keytab \"%s\"\n", keytab); } /* Acquire our credentials */ maj_stat = gss_acquire_cred(&min_stat, gserver, /* desired name */ 0, /* time */ GSS_C_NULL_OID_SET, /* desired mechs */ GSS_C_ACCEPT, /* cred usage */ &gcred, /* handle */ NULL /* actual mechs */, NULL /* time rec */); if (GSS_ERROR(maj_stat)) return exim_gssapi_error_defer(store_reset_point, maj_stat, min_stat, "gss_acquire_cred(%s)", ex_server_str); maj_stat = gss_release_name(&min_stat, &gserver); HDEBUG(D_auth) debug_printf("heimdal: have server credentials.\n"); /* Loop talking to client */ step = 0; from_client = initial_data; handled_empty_ir = FALSE; error_out = OK; /* buffer sizes: auth_get_data() uses big_buffer, which we grow per GSSAPI RFC in _init, if needed, to meet the SHOULD size of 64KB. (big_buffer starts life at the MUST size of 16KB). */ /* step values 0: getting initial data from client to feed into GSSAPI 1: iterating for as long as GSS_S_CONTINUE_NEEDED 2: GSS_S_COMPLETE, SASL wrapping for authz and qop to send to client 3: unpick final auth message from client 4: break/finish (non-step) */ while (step < 4) { switch (step) { case 0: if (!from_client || *from_client == '\0') { if (handled_empty_ir) { HDEBUG(D_auth) debug_printf("gssapi: repeated empty input, grr.\n"); error_out = BAD64; goto ERROR_OUT; } else { HDEBUG(D_auth) debug_printf("gssapi: missing initial response, nudging.\n"); error_out = auth_get_data(&from_client, US"", 0); if (error_out != OK) goto ERROR_OUT; handled_empty_ir = TRUE; continue; } } /* We should now have the opening data from the client, base64-encoded. */ step += 1; HDEBUG(D_auth) debug_printf("heimdal: have initial client data\n"); break; case 1: gbufdesc_in.length = b64decode(from_client, USS &gbufdesc_in.value); if (gclient) { maj_stat = gss_release_name(&min_stat, &gclient); gclient = GSS_C_NO_NAME; } maj_stat = gss_accept_sec_context(&min_stat, &gcontext, /* context handle */ gcred, /* acceptor cred handle */ &gbufdesc_in, /* input from client */ GSS_C_NO_CHANNEL_BINDINGS, /* XXX fixme: use the channel bindings from GnuTLS */ &gclient, /* client identifier */ &mech_type, /* mechanism in use */ &gbufdesc_out, /* output to send to client */ NULL, /* return flags */ NULL, /* time rec */ NULL /* delegated cred_handle */ ); if (GSS_ERROR(maj_stat)) { exim_gssapi_error_defer(NULL, maj_stat, min_stat, "gss_accept_sec_context()"); error_out = FAIL; goto ERROR_OUT; } if (&gbufdesc_out.length != 0) { error_out = auth_get_data(&from_client, gbufdesc_out.value, gbufdesc_out.length); if (error_out != OK) goto ERROR_OUT; gss_release_buffer(&min_stat, &gbufdesc_out); EmptyBuf(gbufdesc_out); } if (maj_stat == GSS_S_COMPLETE) { step += 1; HDEBUG(D_auth) debug_printf("heimdal: GSS complete\n"); } else { HDEBUG(D_auth) debug_printf("heimdal: need more data\n"); } break; case 2: memset(sasl_config, 0xFF, 4); /* draft-ietf-sasl-gssapi-06.txt defines bitmasks for first octet 0x01 No security layer 0x02 Integrity protection 0x04 Confidentiality protection The remaining three octets are the maximum buffer size for wrapped content. */ sasl_config[0] = 0x01; /* Exim does not wrap/unwrap SASL layers after auth */ gbufdesc.value = (void *) sasl_config; gbufdesc.length = 4; maj_stat = gss_wrap(&min_stat, gcontext, 0, /* conf_req_flag: integrity only */ GSS_C_QOP_DEFAULT, /* qop requested */ &gbufdesc, /* message to protect */ NULL, /* conf_state: no confidentiality applied */ &gbufdesc_out /* output buffer */ ); if (GSS_ERROR(maj_stat)) { exim_gssapi_error_defer(NULL, maj_stat, min_stat, "gss_wrap(SASL state after auth)"); error_out = FAIL; goto ERROR_OUT; } HDEBUG(D_auth) debug_printf("heimdal SASL: requesting QOP with no security layers\n"); error_out = auth_get_data(&from_client, gbufdesc_out.value, gbufdesc_out.length); if (error_out != OK) goto ERROR_OUT; gss_release_buffer(&min_stat, &gbufdesc_out); EmptyBuf(gbufdesc_out); step += 1; break; case 3: gbufdesc_in.length = b64decode(from_client, USS &gbufdesc_in.value); maj_stat = gss_unwrap(&min_stat, gcontext, &gbufdesc_in, /* data from client */ &gbufdesc_out, /* results */ NULL, /* conf state */ NULL /* qop state */ ); if (GSS_ERROR(maj_stat)) { exim_gssapi_error_defer(NULL, maj_stat, min_stat, "gss_unwrap(final SASL message from client)"); error_out = FAIL; goto ERROR_OUT; } if (gbufdesc_out.length < 4) { HDEBUG(D_auth) debug_printf("gssapi: final message too short; " "need flags, buf sizes and optional authzid\n"); error_out = FAIL; goto ERROR_OUT; } requested_qop = (CS gbufdesc_out.value)[0]; if ((requested_qop & 0x01) == 0) { HDEBUG(D_auth) debug_printf("gssapi: client requested security layers (%x)\n", (unsigned int) requested_qop); error_out = FAIL; goto ERROR_OUT; } for (i = 0; i < AUTH_VARS; i++) auth_vars[i] = NULL; expand_nmax = 0; /* Identifiers: The SASL provided identifier is an unverified authzid. GSSAPI provides us with a verified identifier, but it might be empty for some clients. */ /* $auth2 is authzid requested at SASL layer */ if (gbufdesc_out.length > 4) { expand_nlength[2] = gbufdesc_out.length - 4; auth_vars[1] = expand_nstring[2] = string_copyn((US gbufdesc_out.value) + 4, expand_nlength[2]); expand_nmax = 2; } gss_release_buffer(&min_stat, &gbufdesc_out); EmptyBuf(gbufdesc_out); /* $auth1 is GSSAPI display name */ maj_stat = gss_display_name(&min_stat, gclient, &gbufdesc_out, &mech_type); if (GSS_ERROR(maj_stat)) { auth_vars[1] = expand_nstring[2] = NULL; expand_nmax = 0; exim_gssapi_error_defer(NULL, maj_stat, min_stat, "gss_display_name(client identifier)"); error_out = FAIL; goto ERROR_OUT; } expand_nlength[1] = gbufdesc_out.length; auth_vars[0] = expand_nstring[1] = string_copyn(gbufdesc_out.value, gbufdesc_out.length); if (expand_nmax == 0) { /* should be: authzid was empty */ expand_nmax = 2; expand_nlength[2] = expand_nlength[1]; auth_vars[1] = expand_nstring[2] = string_copyn(expand_nstring[1], expand_nlength[1]); HDEBUG(D_auth) debug_printf("heimdal SASL: empty authzid, set to dup of GSSAPI display name\n"); } HDEBUG(D_auth) debug_printf("heimdal SASL: happy with client request\n" " auth1 (verified GSSAPI display-name): \"%s\"\n" " auth2 (unverified SASL requested authzid): \"%s\"\n", auth_vars[0], auth_vars[1]); step += 1; break; } /* switch */ } /* while step */ ERROR_OUT: maj_stat = gss_release_cred(&min_stat, &gcred); if (gclient) { gss_release_name(&min_stat, &gclient); gclient = GSS_C_NO_NAME; } if (gbufdesc_out.length) { gss_release_buffer(&min_stat, &gbufdesc_out); EmptyBuf(gbufdesc_out); } if (gcontext != GSS_C_NO_CONTEXT) { gss_delete_sec_context(&min_stat, &gcontext, GSS_C_NO_BUFFER); } store_reset(store_reset_point); if (error_out != OK) return error_out; /* Auth succeeded, check server_condition */ return auth_check_serv_cond(ablock); }
ZLPaintContext* ZLibrary::createContext() { HDEBUG("creating context"); return new BooksPaintContext(); }
void auth_heimdal_gssapi_init(auth_instance *ablock) { krb5_context context; krb5_keytab keytab; krb5_kt_cursor cursor; krb5_keytab_entry entry; krb5_error_code krc; char *principal, *enctype_s; const char *k_keytab_typed_name = NULL; auth_heimdal_gssapi_options_block *ob = (auth_heimdal_gssapi_options_block *)(ablock->options_block); ablock->server = FALSE; ablock->client = FALSE; if (!ob->server_service || !*ob->server_service) { HDEBUG(D_auth) debug_printf("heimdal: missing server_service\n"); return; } krc = krb5_init_context(&context); if (krc != 0) { int kerr = errno; HDEBUG(D_auth) debug_printf("heimdal: failed to initialise krb5 context: %s\n", strerror(kerr)); return; } if (ob->server_keytab) { k_keytab_typed_name = CCS string_sprintf("file:%s", expand_string(ob->server_keytab)); HDEBUG(D_auth) debug_printf("heimdal: using keytab %s\n", k_keytab_typed_name); krc = krb5_kt_resolve(context, k_keytab_typed_name, &keytab); if (krc) { HDEBUG(D_auth) exim_heimdal_error_debug("krb5_kt_resolve", context, krc); return; } } else { HDEBUG(D_auth) debug_printf("heimdal: using system default keytab\n"); krc = krb5_kt_default(context, &keytab); if (krc) { HDEBUG(D_auth) exim_heimdal_error_debug("krb5_kt_default", context, krc); return; } } HDEBUG(D_auth) { /* http://www.h5l.org/manual/HEAD/krb5/krb5_keytab_intro.html */ krc = krb5_kt_start_seq_get(context, keytab, &cursor); if (krc) exim_heimdal_error_debug("krb5_kt_start_seq_get", context, krc); else { while ((krc = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0) { principal = enctype_s = NULL; krb5_unparse_name(context, entry.principal, &principal); krb5_enctype_to_string(context, entry.keyblock.keytype, &enctype_s); debug_printf("heimdal: keytab principal: %s vno=%d type=%s\n", principal ? principal : "??", entry.vno, enctype_s ? enctype_s : "??"); free(principal); free(enctype_s); krb5_kt_free_entry(context, &entry); } krc = krb5_kt_end_seq_get(context, keytab, &cursor); if (krc) exim_heimdal_error_debug("krb5_kt_end_seq_get", context, krc); } } krc = krb5_kt_close(context, keytab); if (krc) HDEBUG(D_auth) exim_heimdal_error_debug("krb5_kt_close", context, krc); krb5_free_context(context); /* RFC 4121 section 5.2, SHOULD support 64K input buffers */ if (big_buffer_size < (64 * 1024)) { uschar *newbuf; big_buffer_size = 64 * 1024; newbuf = store_malloc(big_buffer_size); store_free(big_buffer); big_buffer = newbuf; } ablock->server = TRUE; }