Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Локальные сети персональных компьютеров. Работа с сервером Novell NetWare

© Александр Фролов, Григорий Фролов
Том 9, М.: Диалог-МИФИ, 1993, 168 стр.

[Назад] [Содеожание] [Дальше]

6.2. Просмотр базы объектов

В этом разделе мы рассмотрим задачу сканирования базы данных Bindery с целью получения списка имеющихся в ней объектов. Например, вам может потребоваться список активных серверов в сети, список пользователей или список рабочих групп.

Для получения списка объектов, сведения о которых хранятся в базе данных Bindery, предназначена функция ScanBinderyObject():

int ScanBinderyObject(char *SearchObjectName,
                WORD SearchObjectType, long *ObjectID, char *ObjectName,
                WORD *ObjectType, char *ObjectHasProperties,
                char *ObjectFlag, char *ObjectSecurity);


Эта функция должна использоваться в цикле. При первом вызове в переменную, на которую указывает параметр ObjectID, необходимо записать значение -1. В дальнейшем в эту переменную будет записываться идентификатор найденного объекта.

Для поиска следует указать имя объекта (параметр SearchObjectName) и тип объекта (параметр SearchObjectType). В качестве имени объекта можно использовать шаблон с символами "*" и "?". Тип объекта может быть задан конкретно, либо можно указать значение -1. В последнем случае функция будет искать объекты всех типов. Для того чтобы найти все объекты всех типов, в качестве имени надо указать строку "*", в качестве типа задать значение -1.

Для найденных объектов в соответствующие переменные, указанные параметрами функции, будут записаны имя объекта (параметр ObjectName), тип объекта (параметр ObjectType), флаг (параметр ObjectFlag), байт доступа (параметр ObjectSecurity). Кроме того, в переменную, на которую указывает параметр ObjectHasProperties, записывается значение 0xFF, если объект имеет дополнительную связанную с ним информацию (Properties), которую можно извлечь специально предназначенными для этого функциями.

Функция возвращает 0 при успешном завершении или код ошибки:

Код ошибки Значение
0x96 Мало памяти на сервере
0xEF Имя объекта указано неправильно
0xFC В базе нет объекта с указанным идентификатором
0xFE База данных Bindery заблокирована
0xFF Сбой базы данных Bindery

Ваша программа должна вызывать функцию ScanBinderyObject() в цикле до тех пор, пока она не возвратит код ошибки, отличный от нуля.

Вместо функции ScanBinderyObject() можно использовать функцию E3h прерывания INT 21h:

На входе: AH = E3h;
DS:SI = Адрес буфера запроса;
ES:DI = Адрес буфера ответа.
На выходе: AL = Код ошибки или 0, если операция завершилась без ошибок.

Буфер запроса имеет следующий формат:

struct REQUEST {
        WORD    PacketLength;        // размер пакета запроса
        BYTE    Function;            // должно быть равно 55
        BYTE    ObjectID;            // идентификатор объекта
        WORD    SearchObjectType;    // тип объекта
        BYTE    NameLength;          // длина имени образца для
                                     //   поиска объекта
        BYTE    SearchObjectName[NameLength]; // имя образца для
                                     //   поиска объекта
};


Буфер ответа имеет следующий формат:

struct REPLAY {
        WORD    PacketLength;        // размер пакета
        long    ObjectID;            // идентификатор объекта
        WORD    ObjectType;          // тип объекта
        BYTE    ObjectName[48];      // имя объекта
        BYTE    ObjectFlag;          // флаг объекта
        BYTE    SecurityAccessLevel; // уровень доступа
        BYTE    ObjectHasProperties; // есть записи
};


В базе данных объектов Bindery с каждым объектом может быть связано несколько дополнительных записей, содержащих данные (property). Каждая такая запись имеет свое имя, флаг и байт доступа. Если объект имеет записи, вы можете получить список их имен и других атрибутов при помощи функции ScanProperty():

int ScanProperty(char *ObjectName, WORD ObjectType,
      char *SearchPropertyName, long *SequenceNumber,
      char *PropertyName, char *PropertyFlag,
      char char *PropertySecurity,
      char *PropertyHasValue, char *MoreProperties);


Функция должна вызываться в цикле. При первом вызове переменная, на которую указывает параметр SequenceNumber, должна содержать значение -1. При последующих вызовах содержимое этой переменной будет изменяться автоматически.

Для считывания полей функции необходимо указать имя сканируемого объекта (параметр ObjectName), тип объекта (параметр ObjectType), а также имя записи или шаблон имени записи (параметр SearchPropertyName). В шаблоне можно использовать символы "*" и "?".

Для найденных записей в соответствующие переменные, указанные параметрами функции, будут записаны имя записи (параметр PropertyName), флаг записи (параметр PropertyFlag), байт доступа (параметр PropertySecurity), признак того, что запись имеет значения (параметр PropertyHasValue), признак того, что в объекте есть еще и другие записи (MoreProperties).

Функция возвращает 0 при успешном завершении или код ошибки:

Код ошибки Значение
0x96 Мало памяти на сервере
0xF1 Неправильный код доступа
0xFB Указанная запись не найдена
0xFC В базе нет объекта с указанным идентификатором
0xFE База данных Bindery заблокирована
0xFF Сбой базы данных Bindery

В Novell NetWare для каждого типа объекта существует определенный набор записей, которые могут быть связаны с этим объектом. Например, с объектом типа 1 (обычный пользователь) связаны такие записи, как PASSWORD (пароль) и SECURITY_EQUALS (эквивалентность прав доступа). Содержимое записей можно считать при помощи функции ReadPropertyValue(), которая описана в документации по библиотеке NetWare C Interface. Для этого пользователь, запустивший программу, должен обладать достаточным уровнем доступа.

Приведем некоторые имена полей, определенных в NetWare:

Имя записи Тип объекта

Доступ, запись/чтение

BLOCKS_READ Файл-сервер 3/1
BLOCKS_WRITTEN Файл-сервер 3/1
CONNECT_TIME Файл-сервер 3/1
GROUP_MEMBERS Группа пользователей 3/1
GROUPS_I'M_IN Пользователь 3/1
IDENTIFICATION Пользователь 3/1
NET_ADDRESS Файл-сервер 4/0
OLD_PASSWORDS Пользователь 3/3
OPERATORS Файл-сервер 3/3
PASSWORDS Пользователь 4/4
SECURITY_EQUALS Пользователь 3/2

Полный список полей и подробное их описание вы найдете в документации по библиотеке NetWare C Interface.

6.2.1. Программа BSCAN

Приведем исходный текст программы BSCAN (листинг 27), которая просматривает базу данных объектов. Для каждого найденного объекта программа выводит имя и расшифрованный тип объекта, флаг и уровень доступа. Если объект имеет дополнительные записи (properties), вызывается функция, которая выводит имена найденных записей.

// ===================================================
// Листинг 27. Программа для просмотра содержимого
// базы данных объектов
// Файл bscan\bscan.cpp
//
// (C) A. Frolov, 1993
// ===================================================

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define WORD unsigned int
#define BYTE unsigned char

extern "C" int GetNetWareShellVersion(char *,char *, char *);
extern "C" int ScanBinderyObject(char *, WORD, long *,
                                        char *, WORD *, char *, char *, char *);
extern "C" int ScanProperty(char *, WORD, char *, long *,
                                        char *, char *, char *, char *, char *);

void Property(char *ObjectName, WORD ObjectType);

void main(void) {

        char MajorVersion=0;
        char MinorVersion=0;
        char Revision=0;
        int ccode;

        BYTE ObjectSecurity;
        long ObjectID;
        char SearchObjectName[48];
        char ObjectName[48];
        WORD SearchObjectType;
        WORD ObjectType;
        char ObjectHasProperties;
        char ObjectFlag;

        printf("\n*BSCAN* (C) Frolov A., 1993\n");

// Проверяем присутствие сетевой оболочки

        asm push si
        GetNetWareShellVersion(&MajorVersion,
                        &MinorVersion, &Revision);
        asm pop si

        if(MajorVersion == 0) {
                printf("\nОболочка NetWare не загружена\n");
                return;
        }

// Просматриваем в цикле содержимое базы объектов,
// ищем объекты всех типов

        SearchObjectType = -1;

// Маска для поиска всех объектов

        strcpy(SearchObjectName, "*");

        for(ObjectID = -1;;) {

// Получаем очередной объект

                ccode = ScanBinderyObject(SearchObjectName,
                  SearchObjectType, &ObjectID, ObjectName, &ObjectType,
                  &ObjectHasProperties, &ObjectFlag, &ObjectSecurity);

// Если больше нет объектов или произошла ошибка, завершаем цикл

                if(ccode) break;

// Выводим имя и тип объекта

                printf("\n%-18s\t", ObjectName);

                switch(ObjectType) {
                case 0:
                        printf("???                     "); break;
                case 1:
                        printf("Пользователь            ");        break;
                case 2:
                        printf("Группа                  ");      break;
                case 3:
                        printf("Очередь на печать       "); break;
                case 4:
                        printf("Файл-сервер             "); break;
                case 5:
                        printf("Сервер заданий          "); break;
                case 6:
                        printf("Шлюз                    "); break;
                case 7:
                        printf("Сервер печати           "); break;
                case 8:
                        printf("Очередь архивирования   "); break;
                case 9:
                        printf("Сервер для архивирования"); break;
                case 0xA:
                        printf("Очередь заданий         "); break;
                case 0xb:
                        printf("Администратор           "); break;
                case 0x26:
                        printf("Сервер удаленного моста "); break;
                default:
                  printf("Объект 0x%04.4X           ", ObjectType); break;
                }

// Выводим флаг объекта, который может иметь два значения:
// 0 для постоянных объектов и 1 для временных

                if(ObjectFlag) printf("Временный ");
                else           printf("Постоянный");

// Выводим байт прав, необходимых для получения доступа к объекту

                printf(" Доступ %02.2X", ObjectSecurity);

// Если для объекта имеются дополнительные записи,
// выводим их названия

                if(ObjectHasProperties) Property(ObjectName,
                        ObjectType);
        }
}

// =================================================================
// Функция Property выводит названия дополнительных записей объектов
// =================================================================

void Property(char *ObjectName, WORD ObjectType) {

        int ccode;

        BYTE PropertySecurity;
        long ObjectID;
        char SearchPropertyName[16];
        char PropertyName[16];
        WORD SearchObjectType;
        char PropertyFlag;
        long SequenceNumber;
        char PropertyHasValue;
        char MoreProperties;

// Маска для поиска всех записей

        strcpy(SearchPropertyName, "*");
        for(SequenceNumber=-1;;) {

// Получаем запись

                ccode = ScanProperty(ObjectName, ObjectType,
                  SearchPropertyName, &SequenceNumber,
                  PropertyName, &PropertyFlag, &PropertySecurity,
                  &PropertyHasValue, &MoreProperties);

// Если записей больше нет, завершаем цикл

                if(ccode) break;

// Выводим название записи

                printf("\n\tProperty %s", PropertyName);
        }
}
[Назад] [Содеожание] [Дальше]