1/*
2 * PROGRAM: Client/Server Common Code
3 * MODULE: ClumpletReader.h
4 * DESCRIPTION: Secure handling of clumplet buffers
5 *
6 * The contents of this file are subject to the Initial
7 * Developer's Public License Version 1.0 (the "License");
8 * you may not use this file except in compliance with the
9 * License. You may obtain a copy of the License at
10 * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
11 *
12 * Software distributed under the License is distributed AS IS,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied.
14 * See the License for the specific language governing rights
15 * and limitations under the License.
16 *
17 * The Original Code was created by Nickolay Samofatov
18 * for the Firebird Open Source RDBMS project.
19 *
20 * Copyright (c) 2004 Nickolay Samofatov <nickolay@broadviewsoftware.com>
21 * and all contributors signed below.
22 *
23 * All Rights Reserved.
24 * Contributor(s): ______________________________________.
25 *
26 *
27 */
28
29#ifndef CLUMPLETREADER_H
30#define CLUMPLETREADER_H
31
32#include "../common/classes/alloc.h"
33#include "../common/classes/array.h"
34#include "../common/classes/fb_string.h"
35
36#define DEBUG_CLUMPLETS
37#if defined(DEV_BUILD) && !defined(DEBUG_CLUMPLETS)
38#define DEBUG_CLUMPLETS
39#endif
40
41namespace Firebird {
42
43// This class provides read access for clumplet structure
44// Note: it doesn't make a copy of buffer it reads
45class ClumpletReader : protected AutoStorage
46{
47public:
48 enum Kind
49 {
50 EndOfList,
51 Tagged,
52 UnTagged,
53 SpbAttach,
54 SpbStart,
55 Tpb,
56 WideTagged,
57 WideUnTagged,
58 SpbSendItems,
59 SpbReceiveItems
60 };
61
62 struct KindList
63 {
64 Kind kind;
65 UCHAR tag;
66 };
67
68 struct SingleClumplet
69 {
70 UCHAR tag;
71 size_t size;
72 const UCHAR* data;
73 };
74
75 // Constructor prepares an object from plain PB
76 ClumpletReader(Kind k, const UCHAR* buffer, size_t buffLen);
77 ClumpletReader(MemoryPool& pool, Kind k, const UCHAR* buffer, size_t buffLen);
78
79 // Different versions of clumplets may have different kinds
80 ClumpletReader(const KindList* kl, const UCHAR* buffer, size_t buffLen, FPTR_VOID raise = NULL);
81 ClumpletReader(MemoryPool& pool, const KindList* kl, const UCHAR* buffer, size_t buffLen, FPTR_VOID raise = NULL);
82 virtual ~ClumpletReader() { }
83
84 // Create a copy of reader
85 ClumpletReader(MemoryPool& pool, const ClumpletReader& from);
86 ClumpletReader(const ClumpletReader& from);
87
88 // Navigation in clumplet buffer
89 bool isEof() const { return cur_offset >= getBufferLength(); }
90 void moveNext();
91 void rewind();
92 bool find(UCHAR tag);
93 bool next(UCHAR tag);
94
95 // Methods which work with currently selected clumplet
96 UCHAR getClumpTag() const;
97 size_t getClumpLength() const;
98
99 SLONG getInt() const;
100 bool getBoolean() const;
101 SINT64 getBigInt() const;
102 string& getString(string& str) const;
103 PathName& getPath(PathName& str) const;
104 void getData(UCharBuffer& data) const;
105 const UCHAR* getBytes() const;
106 double getDouble() const;
107 ISC_TIMESTAMP getTimeStamp() const;
108 ISC_TIME getTime() const { return getInt(); }
109 ISC_DATE getDate() const { return getInt(); }
110
111 // get the most generic representation of clumplet
112 SingleClumplet getClumplet() const;
113
114 // Return the tag for buffer (usually structure version)
115 UCHAR getBufferTag() const;
116 // true if buffer has tag
117 bool isTagged() const;
118 size_t getBufferLength() const
119 {
120 size_t rc = getBufferEnd() - getBuffer();
121 if (rc == 1 && kind != UnTagged && kind != SpbStart &&
122 kind != WideUnTagged && kind != SpbSendItems &&
123 kind != SpbReceiveItems)
124 {
125 rc = 0;
126 }
127 return rc;
128 }
129 size_t getCurOffset() const { return cur_offset; }
130 void setCurOffset(size_t newOffset) { cur_offset = newOffset; }
131
132#ifdef DEBUG_CLUMPLETS
133 // Sometimes it's really useful to have it in case of errors
134 void dump() const;
135#endif
136
137 // it is not exact comparison as clumplets may have same tags
138 // but in different order
139 bool simpleCompare(const ClumpletReader &other) const
140 {
141 const size_t len = getBufferLength();
142 return (len == other.getBufferLength()) && (memcmp(getBuffer(), other.getBuffer(), len) == 0);
143 }
144
145protected:
146 enum ClumpletType {TraditionalDpb, SingleTpb, StringSpb, IntSpb, ByteSpb, Wide};
147 ClumpletType getClumpletType(UCHAR tag) const;
148 size_t getClumpletSize(bool wTag, bool wLength, bool wData) const;
149 void adjustSpbState();
150
151 size_t cur_offset;
152 Kind kind;
153 UCHAR spbState; // Reflects state of spb parser/writer
154
155 // Methods are virtual so writer can override 'em
156 virtual const UCHAR* getBuffer() const;
157 virtual const UCHAR* getBufferEnd() const;
158
159 // These functions are called when error condition is detected by this class.
160 // They may throw exceptions. If they don't reader tries to do something
161 // sensible, certainly not overwrite memory or read past the end of buffer
162
163 // This appears to be a programming error in buffer access pattern
164 virtual void usage_mistake(const char* what) const;
165
166 // This is called when passed buffer appears invalid
167 virtual void invalid_structure(const char* what) const;
168
169private:
170 // Assignment not implemented.
171 ClumpletReader& operator=(const ClumpletReader& from);
172
173 const UCHAR* static_buffer;
174 const UCHAR* static_buffer_end;
175
176 static SINT64 fromVaxInteger(const UCHAR* ptr, size_t length);
177 void create(const KindList* kl, size_t buffLen, FPTR_VOID raise);
178
179public:
180 // Some frequently used kind lists
181 static const KindList dpbList[];
182 static const KindList spbList[];
183};
184
185class AuthReader : public ClumpletReader
186{
187public:
188 typedef Array<UCHAR> AuthBlock;
189
190 // name and method are required attributes for any record
191 // name is set by plugin when it calls add()
192 static const unsigned char AUTH_NAME = 0;
193 // method is just a name of plugin which created this record
194 static const unsigned char AUTH_METHOD = 1;
195
196 // additional attributes - only security database is used currently
197 static const unsigned char AUTH_SECURE_DB = 100;
198
199 explicit AuthReader(const AuthBlock& authBlock);
200
201 bool getInfo(string* name, string* method, PathName* secDb);
202};
203
204//#define AUTH_BLOCK_DEBUG
205#ifdef AUTH_BLOCK_DEBUG
206void dumpAuthBlock(const char* text, ClumpletReader* pb, unsigned char param);
207#else
208static inline void dumpAuthBlock(const char*, ClumpletReader*, unsigned char) { }
209#endif
210
211} // namespace Firebird
212
213#endif // CLUMPLETREADER_H
214