1 /* $OpenBSD: clnt_perror.c,v 1.25 2019/07/03 03:24:04 deraadt Exp $ */
2
3 /*
4 * Copyright (c) 2010, Oracle America, Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution.
16 * * Neither the name of the "Oracle America, Inc." nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <rpc/rpc.h>
38 #include <rpc/types.h>
39 #include <rpc/auth.h>
40 #include <rpc/clnt.h>
41
42 static char *auth_errmsg(enum auth_stat stat);
43 #define CLNT_PERROR_BUFLEN 256
44
45 static char buf[CLNT_PERROR_BUFLEN];
46
47 /*
48 * Print reply error info
49 */
50 char *
clnt_sperror(CLIENT * rpch,char * s)51 clnt_sperror(CLIENT *rpch, char *s)
52 {
53 char *err, *str = buf;
54 struct rpc_err e;
55 int ret, len = CLNT_PERROR_BUFLEN;
56
57 CLNT_GETERR(rpch, &e);
58
59 ret = snprintf(str, len, "%s: %s", s, clnt_sperrno(e.re_status));
60 if (ret < 0)
61 ret = 0;
62 else if (ret >= len)
63 goto truncated;
64 str += ret;
65 len -= ret;
66
67 switch (e.re_status) {
68 case RPC_SUCCESS:
69 case RPC_CANTENCODEARGS:
70 case RPC_CANTDECODERES:
71 case RPC_TIMEDOUT:
72 case RPC_PROGUNAVAIL:
73 case RPC_PROCUNAVAIL:
74 case RPC_CANTDECODEARGS:
75 case RPC_SYSTEMERROR:
76 case RPC_UNKNOWNHOST:
77 case RPC_UNKNOWNPROTO:
78 case RPC_PMAPFAILURE:
79 case RPC_PROGNOTREGISTERED:
80 case RPC_FAILED:
81 break;
82
83 case RPC_CANTSEND:
84 case RPC_CANTRECV:
85 ret = snprintf(str, len, "; errno = %s", strerror(e.re_errno));
86 if (ret < 0 || ret >= len)
87 goto truncated;
88 break;
89
90 case RPC_VERSMISMATCH:
91 ret = snprintf(str, len,
92 "; low version = %u, high version = %u",
93 e.re_vers.low, e.re_vers.high);
94 if (ret < 0 || ret >= len)
95 goto truncated;
96 break;
97
98 case RPC_AUTHERROR:
99 ret = snprintf(str, len, "; why = ");
100 if (ret < 0)
101 ret = 0;
102 else if (ret >= len)
103 goto truncated;
104 str += ret;
105 len -= ret;
106 err = auth_errmsg(e.re_why);
107 if (err != NULL) {
108 ret = snprintf(str, len, "%s", err);
109 if (ret < 0 || ret >= len)
110 goto truncated;
111 } else {
112 ret = snprintf(str, len,
113 "(unknown authentication error - %d)",
114 (int) e.re_why);
115 if (ret < 0 || ret >= len)
116 goto truncated;
117 }
118 break;
119
120 case RPC_PROGVERSMISMATCH:
121 ret = snprintf(str, len,
122 "; low version = %u, high version = %u",
123 e.re_vers.low, e.re_vers.high);
124 if (ret < 0 || ret >= len)
125 goto truncated;
126 break;
127
128 default: /* unknown */
129 ret = snprintf(str, len, "; s1 = %u, s2 = %u",
130 e.re_lb.s1, e.re_lb.s2);
131 if (ret < 0 || ret >= len)
132 goto truncated;
133 break;
134 }
135 if (strlcat(buf, "\n", CLNT_PERROR_BUFLEN) >= CLNT_PERROR_BUFLEN)
136 goto truncated;
137 return (buf);
138
139 truncated:
140 snprintf(buf + CLNT_PERROR_BUFLEN - 5, 5, "...\n");
141 return (buf);
142 }
143 DEF_WEAK(clnt_sperror);
144
145 void
clnt_perror(CLIENT * rpch,char * s)146 clnt_perror(CLIENT *rpch, char *s)
147 {
148 (void) fprintf(stderr, "%s", clnt_sperror(rpch, s));
149 }
150 DEF_WEAK(clnt_perror);
151
152 static const char *const rpc_errlist[] = {
153 "RPC: Success", /* 0 - RPC_SUCCESS */
154 "RPC: Can't encode arguments", /* 1 - RPC_CANTENCODEARGS */
155 "RPC: Can't decode result", /* 2 - RPC_CANTDECODERES */
156 "RPC: Unable to send", /* 3 - RPC_CANTSEND */
157 "RPC: Unable to receive", /* 4 - RPC_CANTRECV */
158 "RPC: Timed out", /* 5 - RPC_TIMEDOUT */
159 "RPC: Incompatible versions of RPC", /* 6 - RPC_VERSMISMATCH */
160 "RPC: Authentication error", /* 7 - RPC_AUTHERROR */
161 "RPC: Program unavailable", /* 8 - RPC_PROGUNAVAIL */
162 "RPC: Program/version mismatch", /* 9 - RPC_PROGVERSMISMATCH */
163 "RPC: Procedure unavailable", /* 10 - RPC_PROCUNAVAIL */
164 "RPC: Server can't decode arguments", /* 11 - RPC_CANTDECODEARGS */
165 "RPC: Remote system error", /* 12 - RPC_SYSTEMERROR */
166 "RPC: Unknown host", /* 13 - RPC_UNKNOWNHOST */
167 "RPC: Port mapper failure", /* 14 - RPC_PMAPFAILURE */
168 "RPC: Program not registered", /* 15 - RPC_PROGNOTREGISTERED */
169 "RPC: Failed (unspecified error)", /* 16 - RPC_FAILED */
170 "RPC: Unknown protocol" /* 17 - RPC_UNKNOWNPROTO */
171 };
172
173
174 /*
175 * This interface for use by clntrpc
176 */
177 char *
clnt_sperrno(enum clnt_stat stat)178 clnt_sperrno(enum clnt_stat stat)
179 {
180 unsigned int errnum = stat;
181
182 if (errnum < (sizeof(rpc_errlist)/sizeof(rpc_errlist[0])))
183 return (char *)rpc_errlist[errnum];
184
185 return ("RPC: (unknown error code)");
186 }
187 DEF_WEAK(clnt_sperrno);
188
189 void
clnt_perrno(enum clnt_stat num)190 clnt_perrno(enum clnt_stat num)
191 {
192 (void) fprintf(stderr, "%s\n", clnt_sperrno(num));
193 }
194
195
196 char *
clnt_spcreateerror(char * s)197 clnt_spcreateerror(char *s)
198 {
199 switch (rpc_createerr.cf_stat) {
200 case RPC_PMAPFAILURE:
201 (void) snprintf(buf, CLNT_PERROR_BUFLEN, "%s: %s - %s\n", s,
202 clnt_sperrno(rpc_createerr.cf_stat),
203 clnt_sperrno(rpc_createerr.cf_error.re_status));
204 break;
205
206 case RPC_SYSTEMERROR:
207 (void) snprintf(buf, CLNT_PERROR_BUFLEN, "%s: %s - %s\n", s,
208 clnt_sperrno(rpc_createerr.cf_stat),
209 strerror(rpc_createerr.cf_error.re_errno));
210 break;
211
212 default:
213 (void) snprintf(buf, CLNT_PERROR_BUFLEN, "%s: %s\n", s,
214 clnt_sperrno(rpc_createerr.cf_stat));
215 break;
216 }
217 buf[CLNT_PERROR_BUFLEN-2] = '\n';
218 buf[CLNT_PERROR_BUFLEN-1] = '\0';
219 return (buf);
220 }
221 DEF_WEAK(clnt_spcreateerror);
222
223 void
clnt_pcreateerror(char * s)224 clnt_pcreateerror(char *s)
225 {
226 fprintf(stderr, "%s", clnt_spcreateerror(s));
227 }
228 DEF_WEAK(clnt_pcreateerror);
229
230 static const char *const auth_errlist[] = {
231 "Authentication OK", /* 0 - AUTH_OK */
232 "Invalid client credential", /* 1 - AUTH_BADCRED */
233 "Server rejected credential", /* 2 - AUTH_REJECTEDCRED */
234 "Invalid client verifier", /* 3 - AUTH_BADVERF */
235 "Server rejected verifier", /* 4 - AUTH_REJECTEDVERF */
236 "Client credential too weak", /* 5 - AUTH_TOOWEAK */
237 "Invalid server verifier", /* 6 - AUTH_INVALIDRESP */
238 "Failed (unspecified error)" /* 7 - AUTH_FAILED */
239 };
240
241 static char *
auth_errmsg(enum auth_stat stat)242 auth_errmsg(enum auth_stat stat)
243 {
244 unsigned int errnum = stat;
245
246 if (errnum < (sizeof(auth_errlist)/sizeof(auth_errlist[0])))
247 return (char *)auth_errlist[errnum];
248
249 return (NULL);
250 }
251