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 | |
41 | namespace Firebird { |
42 | |
43 | // This class provides read access for clumplet structure |
44 | // Note: it doesn't make a copy of buffer it reads |
45 | class ClumpletReader : protected AutoStorage |
46 | { |
47 | public: |
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 | |
145 | protected: |
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 | |
169 | private: |
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 | |
179 | public: |
180 | // Some frequently used kind lists |
181 | static const KindList dpbList[]; |
182 | static const KindList spbList[]; |
183 | }; |
184 | |
185 | class AuthReader : public ClumpletReader |
186 | { |
187 | public: |
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 |
206 | void dumpAuthBlock(const char* text, ClumpletReader* pb, unsigned char param); |
207 | #else |
208 | static inline void dumpAuthBlock(const char*, ClumpletReader*, unsigned char) { } |
209 | #endif |
210 | |
211 | } // namespace Firebird |
212 | |
213 | #endif // CLUMPLETREADER_H |
214 | |