32
32
* LIBTAC_STATUS_PROTOCOL_ERR
33
33
* >= 0 : server response, see TAC_PLUS_AUTHEN_STATUS_...
34
34
*/
35
- int tac_acct_read ( int fd , struct areply * re ) {
36
- HDR th ;
35
+ int tac_acct_parse ( u_char * pkt , unsigned pkt_total , struct areply * re ) {
36
+ HDR * th = ( HDR * ) pkt ;
37
37
struct acct_reply * tb = NULL ;
38
38
size_t ulen_from_header , len_from_body ;
39
- ssize_t spacket_read ;
40
39
char * msg = NULL ;
41
- int timeleft = 0 ;
42
- re -> attr = NULL ; /* unused */
43
- re -> msg = NULL ;
44
-
45
- if (tac_readtimeout_enable &&
46
- tac_read_wait (fd ,tac_timeout * 1000 , TAC_PLUS_HDR_SIZE ,& timeleft ) < 0 ) {
47
- TACSYSLOG (LOG_ERR ,\
48
- "%s: reply timeout after %u secs" , __FUNCTION__ , tac_timeout );
49
- re -> msg = xstrdup (acct_syserr_msg );
50
- re -> status = LIBTAC_STATUS_READ_TIMEOUT ;
51
- free (tb );
52
- return re -> status ;
53
- }
54
40
55
- spacket_read = read (fd , & th , TAC_PLUS_HDR_SIZE );
56
- if (spacket_read < TAC_PLUS_HDR_SIZE ) {
57
- TACSYSLOG (LOG_ERR ,\
58
- "%s: short reply header, read %zd of %u expected: %m" , __FUNCTION__ ,\
59
- spacket_read , TAC_PLUS_HDR_SIZE );
60
- re -> msg = xstrdup (acct_syserr_msg );
61
- re -> status = LIBTAC_STATUS_SHORT_HDR ;
62
- free (tb );
63
- return re -> status ;
64
- }
41
+ re -> attr = NULL ; /* unused */
42
+ re -> msg = re -> data = NULL ;
65
43
66
44
/* check the reply fields in header */
67
- msg = _tac_check_header (& th , TAC_PLUS_ACCT );
45
+ msg = _tac_check_header (th , TAC_PLUS_ACCT );
68
46
if (msg != NULL ) {
69
47
re -> msg = xstrdup (msg );
70
48
re -> status = LIBTAC_STATUS_PROTOCOL_ERR ;
71
- free (tb );
72
49
TACDEBUG (LOG_DEBUG , "%s: exit status=%d, status message \"%s\"" ,\
73
50
__FUNCTION__ , re -> status , re -> msg != NULL ? re -> msg : "" );
74
51
return re -> status ;
75
52
}
76
53
77
- ulen_from_header = ntohl (th .datalength );
78
- if (ulen_from_header > TAC_PLUS_MAX_PACKET_SIZE ) {
79
- TACSYSLOG (LOG_ERR ,\
80
- "%s: length declared in the packet %zu exceeds max allowed packet size %d" ,\
81
- __FUNCTION__ ,\
82
- ulen_from_header , TAC_PLUS_MAX_PACKET_SIZE );
83
- re -> status = LIBTAC_STATUS_SHORT_HDR ;
84
- free (tb );
85
- return re -> status ;
86
- }
87
- tb = (struct acct_reply * ) xcalloc (1 , ulen_from_header );
54
+ ulen_from_header = ntohl (th -> datalength );
88
55
89
- /* read reply packet body */
90
- if (tac_readtimeout_enable &&
91
- tac_read_wait (fd ,timeleft ,ulen_from_header ,NULL ) < 0 ) {
92
- TACSYSLOG (LOG_ERR ,\
93
- "%s: reply timeout after %u secs" , __FUNCTION__ , tac_timeout );
94
- re -> msg = xstrdup (acct_syserr_msg );
95
- re -> status = LIBTAC_STATUS_READ_TIMEOUT ;
96
- free (tb );
97
- return re -> status ;
98
- }
56
+ tb = (struct acct_reply * )(pkt + TAC_PLUS_HDR_SIZE );
99
57
100
- spacket_read = read (fd , tb , ulen_from_header );
101
- if (spacket_read < (ssize_t ) ulen_from_header ) {
58
+ if (pkt_total != ulen_from_header ) {
102
59
TACSYSLOG (LOG_ERR ,\
103
- "%s: short reply body, read %zd of %zu: %m" ,\
60
+ "%s: short packet, got %u expected %zu: %m" ,\
104
61
__FUNCTION__ ,\
105
- spacket_read , ulen_from_header );
62
+ pkt_total , TAC_PLUS_HDR_SIZE + ulen_from_header );
106
63
re -> msg = xstrdup (acct_syserr_msg );
107
64
re -> status = LIBTAC_STATUS_SHORT_BODY ;
108
- free (tb );
109
65
return re -> status ;
110
66
}
111
67
112
68
/* decrypt the body */
113
- _tac_crypt ((u_char * ) tb , & th );
69
+ _tac_crypt ((u_char * ) tb , th );
114
70
115
71
/* Convert network byte order to host byte order */
116
72
tb -> msg_len = ntohs (tb -> msg_len );
117
73
tb -> data_len = ntohs (tb -> data_len );
118
74
119
75
/* check the length fields */
120
- len_from_body = sizeof ( tb -> msg_len ) + sizeof ( tb -> data_len ) +
121
- sizeof ( tb -> status ) + tb -> msg_len + tb -> data_len ;
76
+ len_from_body = TAC_ACCT_REPLY_FIXED_FIELDS_SIZE + \
77
+ tb -> msg_len + tb -> data_len ;
122
78
123
79
if (ulen_from_header != len_from_body ) {
124
80
TACSYSLOG (LOG_ERR ,\
125
- "%s: inconsistent reply body, incorrect key? " ,\
126
- __FUNCTION__ );
81
+ "%s: inconsistent reply body, header len %zu versus parsed len %zu " ,\
82
+ __FUNCTION__ , ulen_from_header , len_from_body );
127
83
re -> msg = xstrdup (acct_syserr_msg );
128
84
re -> status = LIBTAC_STATUS_PROTOCOL_ERR ;
129
- free (tb );
130
85
return re -> status ;
131
86
}
132
87
133
88
/* save status and clean up */
134
89
if (tb -> msg_len ) {
135
90
msg = (char * ) xcalloc (1 , tb -> msg_len + 1 );
136
91
bcopy ((u_char * ) tb + TAC_ACCT_REPLY_FIXED_FIELDS_SIZE , msg , tb -> msg_len );
137
- msg [( int ) tb -> msg_len ] = '\0' ;
92
+ msg [tb -> msg_len ] = '\0' ;
138
93
re -> msg = msg ; /* Freed by caller */
139
94
}
140
95
96
+ if (tb -> data_len ) {
97
+ msg = (char * ) xcalloc (1 , tb -> data_len + 1 );
98
+ bcopy ((u_char * ) tb + TAC_ACCT_REPLY_FIXED_FIELDS_SIZE + tb -> data_len ,
99
+ msg , tb -> data_len );
100
+ msg [tb -> data_len ] = '\0' ;
101
+ re -> data = msg ; /* Freed by caller */
102
+ }
103
+
141
104
/* server logged our request successfully */
142
105
if (tb -> status == TAC_PLUS_ACCT_STATUS_SUCCESS ) {
143
106
TACDEBUG (LOG_DEBUG , "%s: accounted ok" , __FUNCTION__ );
144
107
if (!re -> msg ) re -> msg = xstrdup (acct_ok_msg );
145
108
re -> status = tb -> status ;
146
- free (tb );
147
109
return re -> status ;
148
110
}
149
111
@@ -162,6 +124,94 @@ int tac_acct_read(int fd, struct areply *re) {
162
124
break ;
163
125
}
164
126
165
- free (tb );
166
127
return re -> status ;
167
- }
128
+ } /* tac_acct_parse */
129
+
130
+ /*
131
+ * return value:
132
+ * < 0 : error status code, see LIBTAC_STATUS_...
133
+ * LIBTAC_STATUS_READ_TIMEOUT
134
+ * LIBTAC_STATUS_SHORT_HDR
135
+ * LIBTAC_STATUS_SHORT_BODY
136
+ * LIBTAC_STATUS_PROTOCOL_ERR
137
+ * >= 0 : server response, see TAC_PLUS_AUTHEN_STATUS_...
138
+ */
139
+ int tac_acct_read (int fd , struct areply * re ) {
140
+ HDR * th ;
141
+ struct acct_reply * tb = NULL ;
142
+ size_t ulen_from_header ;
143
+ ssize_t spacket_read ;
144
+ int status , timeleft = 0 ;
145
+
146
+ re -> attr = NULL ; /* unused */
147
+ re -> msg = re -> data = NULL ;
148
+
149
+ if (tac_readtimeout_enable &&
150
+ tac_read_wait (fd , tac_timeout * 1000 , TAC_PLUS_HDR_SIZE , & timeleft ) < 0 ) {
151
+ TACSYSLOG (LOG_ERR ,\
152
+ "%s: reply timeout after %u secs" , __FUNCTION__ , tac_timeout );
153
+ re -> msg = xstrdup (acct_syserr_msg );
154
+ re -> status = LIBTAC_STATUS_READ_TIMEOUT ;
155
+ return re -> status ;
156
+ }
157
+
158
+ th = (HDR * )xcalloc (1 , TAC_PLUS_HDR_SIZE );
159
+
160
+ spacket_read = read (fd , (char * )th , TAC_PLUS_HDR_SIZE );
161
+ if (spacket_read < TAC_PLUS_HDR_SIZE ) {
162
+ TACSYSLOG (LOG_ERR ,\
163
+ "%s: short reply header, read %zd of %u expected: %m" , __FUNCTION__ ,\
164
+ ((spacket_read >= 0 ) ? spacket_read : 0 ), TAC_PLUS_HDR_SIZE );
165
+ re -> msg = xstrdup (acct_syserr_msg );
166
+ re -> status = LIBTAC_STATUS_SHORT_HDR ;
167
+ free (th );
168
+ return re -> status ;
169
+ }
170
+
171
+ ulen_from_header = ntohl (th -> datalength );
172
+ if (ulen_from_header > TAC_PLUS_MAX_PACKET_SIZE ) {
173
+ TACSYSLOG (LOG_ERR ,\
174
+ "%s: length declared in the packet %zu exceeds max allowed packet size %u" , __FUNCTION__ ,\
175
+ ulen_from_header , TAC_PLUS_MAX_PACKET_SIZE );
176
+ re -> msg = xstrdup (acct_syserr_msg );
177
+ re -> status = LIBTAC_STATUS_PROTOCOL_ERR ;
178
+ free (th );
179
+ return re -> status ;
180
+ }
181
+
182
+ /* now make room for entire contiguous packet */
183
+ th = (HDR * )xrealloc (th , TAC_PLUS_HDR_SIZE + ulen_from_header );
184
+ tb = (struct acct_reply * )((u_char * )th + TAC_PLUS_HDR_SIZE );
185
+
186
+ /* read reply packet body */
187
+ if (tac_readtimeout_enable &&
188
+ tac_read_wait (fd , timeleft , ulen_from_header , NULL ) < 0 ) {
189
+ TACSYSLOG (LOG_ERR ,\
190
+ "%s: reply timeout after %u secs" , __FUNCTION__ , tac_timeout );
191
+ re -> msg = xstrdup (acct_syserr_msg );
192
+ re -> status = LIBTAC_STATUS_READ_TIMEOUT ;
193
+ free (th );
194
+ return re -> status ;
195
+ }
196
+
197
+ spacket_read = read (fd , (char * )tb , ulen_from_header );
198
+ if (spacket_read < 0 || (size_t ) spacket_read < ulen_from_header ) {
199
+ TACSYSLOG (LOG_ERR ,\
200
+ "%s: short reply body, read %zd of %zu: %m" ,\
201
+ __FUNCTION__ ,\
202
+ ((spacket_read >= 0 ) ? spacket_read : 0 ), ulen_from_header );
203
+ re -> msg = xstrdup (acct_syserr_msg );
204
+ re -> status = LIBTAC_STATUS_SHORT_BODY ;
205
+ free (th );
206
+ return re -> status ;
207
+ }
208
+
209
+ /* now parse remaining packet fields */
210
+ status = tac_acct_parse ((u_char * )th , TAC_PLUS_HDR_SIZE + ulen_from_header , re );
211
+
212
+ /* all useful data has been copied out */
213
+ free (th );
214
+
215
+ return status ;
216
+ } /* tac_acct_read */
217
+
0 commit comments