Опубликован: 04.07.2008 | Доступ: свободный | Студентов: 637 / 33 | Оценка: 4.83 / 5.00 | Длительность: 42:11:00
Дополнительный материал 2:

Пример программы DSAPI

Пример исходного кода

В последующих трех примерах приведен исходный код для примера DSAPI-фильтра.

/******************************************************************
ПРОГРАММА: SECDOM
ФАЙЛ: SECDOM.C (основная программа)
618 Приложение B
НАЗНАЧЕНИЕ: Пример программы C API, демонстрирующей создание
библиотеки, выполняющей аутентификацию пользователя Domino
через Web с использованием учетной записи пользователя в операционной 
системе через DSAPI.
******************************************************************/
/* Включаемые файлы ввода-вывода */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* Включаемые файлы Notes SDK */
#include "global.h"
#include "osmem.h"
#include "lookup.h"
#include "dsapi.h"
#include "addin.h"
#define MAX_BUF_LEN 512
#define USER_DOMAIN_SEPARATOR "@"
/*---
* прототипы локальных процедур
*/
/* Точка входа общей библиотеки Notes SDK для Unix */
STATUS FAR PASCAL MainEntryPoint (void);
/* Процедуры с синтаксисом, требуемым интерфейсом DSAPI */
unsigned int Authenticate(FilterContext* context, FilterAuthenticate*
authData);
/* Извлечение имен из адресной книги Notes */
int getUserNames (FilterContext* context,
char *userName,
char **pUserFullName,
int *pUserFullNameLen,
char **pUserShortName,
int *pUserShortNameLen);
int getLookupInfo (FilterContext* context,
char *pMatch,
unsigned short itemNumber,
char **pInfo,
int *pInfoLen);
int doAuthenticate(char *userName, char *domain, char *password);
#ifdef UNIX
int unixAuthenticate(char *userName, char *password);
#else
int separateUsernameAndDomainname(char *userName,char *separator,char
**user,char**domain);
int winAuthenticate(char *userName, char *domain, char *password);
#endif
/*---
* далее приведены локальные процедуры
*/
STATUS FAR PASCAL MainEntryPoint (void)
{/
*
* Описание: Обеспечение основной точки входа Notes API для
* инициализации в этой общей библиотеке. Нам нужна эта точка входа,
* потому что мы хотим иметь возможность просматривать информацию
* пользователей в адресной книге через
* Notes SDK API.
**
Ввод: нет
* Вывод: нет
* Возврат: NOERROR
*/
return NOERROR;
}/
*---
* инициализация фильтра
*/
unsigned int FilterInit(FilterInitData* filterInitData)
{/
*
* Описание: Инициализация фильтра выполняется при динамической загрузке
* общей библиотеки файльтра.
**
Ввод: спецификация filterInitData dsapi контролирует формат
* данных
* Вывод: заполняются некоторые поля filterInitData
**
Возврат: kFilterHandledEvent
*/
printf("\nFilterInitData() is getting called.\n");
/*Обязательно*/
filterInitData->appFilterVersion = kInterfaceVersion;
/* Измените следующий код, установив требуемые флаги */
filterInitData->eventFlags = kFilterAuthenticate;
/* Задайте короткое описание своего фильтра */
strcpy(filterInitData->filterDesc,
"Operating System Authentication Filter");
/* здесь можно вставить код глобальной инициализации... */
/* Выходные данные, направляемые в stdout и stderr, выводятся в
* консоли сервера, но не записываются в файл журнала сервера.
*/
printf("\nDSAPI Authentication filter initialized\n");
return kFilterHandledEvent;
}/
*---
* завершение работы фильтра
*/
unsigned int TerminateFilter(unsigned int reserved)
{/
*
* Описание: Завершение работы фильтра выполняется при выгрузке
* общей библиотеки фильтра.
**
Ввод: зарезервирован, не используется (спецификация dsapi контролирует
* формат данных)
* Вывод: нет
**
Возврат: kFilterHandledEvent
*/
/* здесь можно вставить код глобальной очистки... */
return kFilterHandledEvent;
}/
*---
* обработка уведомлений фильтра
*/
unsigned int HttpFilterProc(FilterContext* context,
unsigned int eventType, void* eventData)
{/
*
* Описание: Эта процедура вызывается для обработки всех событий
dsapi-фильтра.
**
Ввод: зарезервирован, не используется (спецификация dsapi контролирует
* формат данных)
* Вывод: нет
**
Возврат: kFilterNotHandled для всех ненастроенных событий,
* в противном случае позволяет процедуре фильтра задать возвращаемое * значение.
*/
/* Нужно включить только те события, которые требуется обрабатывать
*/
switch (eventType) {
case kFilterAuthenticate:
return Authenticate(context, (FilterAuthenticate *)eventData);
default:
break;
}r
eturn kFilterNotHandled;
}/
*---
* обработка аутентификации пользователей
*/
unsigned int Authenticate(FilterContext* context,
FilterAuthenticate* authData)
{/
*
* Описание: Эта процедура вызывается при возникновении
* события dsapi kFilterAuthUser.
**
Ввод: контекстная спецификация dsapi контролирует формат данных
**
поле пароля authData содержит пароль, предназначенный для использования
* при аутентификации
* поле userName содержит имя
* для аутентификации
* поле foundInCache = TRUE, если
* пользователь был найден в кeше и можно провести
* его аутентификацию.
**
Вывод: в поле authType authName вводится отличительное имя
* пользователя
* в поле authType filed вводится
* kNotAuthentic - если нельзя выполнить аутентификацию пользователя
* kAuthenticBasic - если можно выполнить аутентификацию
* пользователя.
**
Возврат: kFilterNotHandled - если входные данные непонятны,
* или если пользователь был найден в кeше, или
* если обнаружилось, что аутентифицируемый пользователь
* не задан в операционной системе.
* kFilterHandledEvent - если пользователь задан в операционной
системе.
*/
/* Если пользователь найден в кeше, выполнение дополнительных действий * не требуется.
*/
if (!authData || authData->foundInCache) {
AddInLogMessageText ("\n user is found in the cache \n", NOERROR);
return kFilterNotHandled;
}/
* Попытка проверить пароль пользователя.
*/
if (authData->userName && authData->password) {
char *fullName = NULL;
int fullNameLen = 0;
char *shortName = NULL;
int shortNameLen = 0;
char *user = NULL;
char *domain = NULL;
#if defined SOLARIS || AIX
user=(char*)authData->userName;
#else
separateUsernameAndDomainname(authData->userName,USER_DOMAIN_SEPARA
TOR,&user,&domain);
#endif
/* Просмотр пользователя в адресной книге. Получение
* короткого имени пользователя (ожидается, что оно соответствует
* имени пользователя в ОС) и получение полного имени пользователя
* (ожидается, что оно будет иметь формат, подлежащий передаче обратно в * dsapi).
*/
if (NOERROR == getUserNames (context,
user,
&fullName,
&fullNameLen,
&shortName,
&shortNameLen) )
{/
* Аутентификация имени пользователя/пароля в ОС */
if (NOERROR != doAuthenticate(shortName, domain,
Пример программы DSAPI 623
(char *)authData->password))
{r
eturn kFilterNotHandled;
}e
lse
{/
* Копирование канонического имени этого пользователя,
* требуемого dsapi. */
strncpy ((char *)authData->authName, fullName,
authData->authNameSize);
authData->authType = kAuthenticBasic;
authData->foundInCache = TRUE;
}r
eturn kFilterHandledEvent;
}}r
eturn kFilterNotHandled;
}i
nt getUserNames (FilterContext* context,
char *userName,
char **pUserFullName,
int *pUserFullNameLen,
char **pUserShortName,
int *pUserShortNameLen) {
/*
* Описание: Просмотр пользователя и возврат полного и короткого
* имени пользователя.
**
Ввод: context - контекст, используемый для выделения памяти
* userName - имя пользователя, для которого выполняется просмотр
* Вывод: pUserFullName - расположение полного имени пользователя
* pUserFullNameLen - расположение для хранения длины полного имени
* pUserShortName – расположение короткого имени пользователя
* pUserShortNameLen - расположение для хранения длины короткого
имени
**
Возврат: -1 - ошибка, 0 - успех
*/
STATUS error = NOERROR;
HANDLE hLookup = NULLHANDLE;
DWORD Matches = 0;
char *pLookup;
char *pName = NULL;
char *pMatch = NULL;
int rc = -1;
/* Инициализация вывода */
*pUserFullName = NULL;
*pUserFullNameLen = 0;
*pUserShortName = NULL;
*pUserShortNameLen = 0;
/* do the name lookup
*/
error = NAMELookup2(NULL, /* NULL означает локальный просмотр */
0, /* флаги */
1, /* количество пространств имен */
"$Users", /* список пространств имен */
1, /* количество имен, для которых требуется выполнить просмотр */
userName, /* список имен, для которых требуется выполнить просмотр */
2, /* количество возвращаемых элементов */
"FullName\0ShortName", /* список возвращаемых
* элементов */
&hLookup); /* место для получения дескриптора
* буфера возврата */
if (error || (NULLHANDLE == hLookup))
goto NoUnlockExit;
pLookup = (char *) OSLockObject(hLookup);
/* Получение указателя нашей записи.
*/
pName = (char *)NAMELocateNextName2(pLookup, /* буфер просмотра
* имени */
NULL, /* начинать в начале
* буфера просмотра */
&Matches); /* Получает количество
* найденных записей
* (должно быть равно 1) */
/* Если запись не найдена - выход */
if ((pName == NULL) || (Matches <= 0)) {
goto Exit;
}p
Match = (char *)NAMELocateNextMatch2(pLookup, /* буфер просмотра
* имени */
pName, /* найденная нами запись */
NULL); /* предыдущих соответствий нет */
if (NULL == pMatch) {
goto Exit;
}
/* Извлечение полного имени из полученной информации */
if ( getLookupInfo (context,
pMatch,
0,
pUserFullName,
pUserFullNameLen) )
goto Exit;
AddInLogMessageText ("full name=%s,length=%d\n", 0,*pUserFullName,*
pUserFullNameLen);
/* Извлечение короткого имени из полученной информации */
if ( getLookupInfo (context,
pMatch,
1,
pUserShortName,
pUserShortNameLen) )
goto Exit;
else
rc = 0;
AddInLogMessageText ("short name=%s,length=%d\n", 0,*pUserShortName
,*pUserShortNameLen);
Exit:
if ( pLookup && hLookup )
OSUnlock(hLookup);
NoUnlockExit:
if (NULLHANDLE != hLookup)
OSMemFree(hLookup);
return rc;
}i
nt getLookupInfo (FilterContext* context,
char *pMatch,
unsigned short itemNumber,
char **pInfo,
int *pInfoLen) {
/*
* Описание: Извлечение информации из буфера просмотра
*
* Ввод: context - контекст, используемый для выделения памяти
* pMatch – имя буфера просмотра
* itemNumber – место хранения информации в буфере просмотра
* Вывод: pInfo – расположение буфера информации
* pInfoLen – место хранения длины информации
*
* Возврат: -1 - ошибка, 0 - успех
*/
unsigned int reserved = 0;
unsigned int errID;
char *ValuePtr = NULL;
WORD ValueLength, DataType;
STATUS error;
void *newSpace = NULL;
/* Инициализация вывода */
*pInfo = NULL;
*pInfoLen = 0;
/* Проверка типа и длины информации */
ValuePtr = (char *)NAMELocateItem2(pMatch,
itemNumber,
&DataType,
&ValueLength);
if (NULL == ValuePtr || ValueLength == 0) {
return -1;
}V
alueLength -= sizeof(WORD);
/* проверка значения DataType */
switch (DataType) {
case TYPE_TEXT_LIST:
break;
case TYPE_TEXT:
break;
default:
return -1;
}/
* Выделение пространства для информации. Эта память освобождается
* автоматически при завершении работы потока.
*/
newSpace = (context->AllocMem)(context, ValueLength+1,
reserved, &errID);
*pInfo = (char *) newSpace;
if (NULL == *pInfo) {
printf ("Out of memory\n");
return -1;
}/
* Получение информации */
error = NAMEGetTextItem2(pMatch, /* найденное соответствие */
itemNumber, /* номер элемента в порядке
* просмотра элементов */
0, /* Номер элемента в текстовых
* списках */
*pInfo, /* буфер для копирования
* результата */
MAX_BUF_LEN); /* Длина буфера */
if (!error) {
*pInfoLen = strlen(*pInfo)+1;
return 0;
}r
eturn -1;
}
int doAuthenticate(char *userName, char *domain, char *password) {
/*
* Описание: Проверяет, существует ли пользователь в операционной системе
* Если существует, определяет, можно ли проверить пароль.
**
Ввод: userName - имя пользователя
* domain - имя домена (NULL - UNIX)
* password - пароль
**
Возврат: -1 - ошибка, 0 - успех
*/
if (!userName) {
AddInLogMessageText ("\nERROR: User must be specified\n", NOERROR);
return -1;
}#
if defined SOLARIS || AIX
printf("\nin doAuthenticate()\n");
return(unixAuthenticate(userName, password));
#else
if (!domain) {
AddInLogMessageText ("\nERROR: Domain must be specified. Use username@
domainname format\n",
NOERROR);
return -1;
}r
eturn(winAuthenticate(userName, domain, password));
#endif
}/
* ----- конец secdom.c */
Пример B.1. Основная программа