1 /* xstart.c --- Start libgsasl session.
2 * Copyright (C) 2002-2021 Simon Josefsson
3 *
4 * This file is part of GNU SASL Library.
5 *
6 * GNU SASL Library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
10 *
11 * GNU SASL Library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License License along with GNU SASL Library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "internal.h"
24
25 static Gsasl_mechanism *
find_mechanism(const char * mech,size_t n_mechs,Gsasl_mechanism * mechs)26 find_mechanism (const char *mech, size_t n_mechs, Gsasl_mechanism * mechs)
27 {
28 size_t i;
29
30 if (mech == NULL)
31 return NULL;
32
33 for (i = 0; i < n_mechs; i++)
34 if (strcmp (mech, mechs[i].name) == 0)
35 return &mechs[i];
36
37 return NULL;
38 }
39
40 static int
setup(Gsasl * ctx,const char * mech,Gsasl_session * sctx,size_t n_mechs,Gsasl_mechanism * mechs,int clientp)41 setup (Gsasl * ctx,
42 const char *mech,
43 Gsasl_session * sctx,
44 size_t n_mechs, Gsasl_mechanism * mechs, int clientp)
45 {
46 Gsasl_mechanism *mechptr = NULL;
47 int res;
48
49 mechptr = find_mechanism (mech, n_mechs, mechs);
50 if (mechptr == NULL)
51 return GSASL_UNKNOWN_MECHANISM;
52
53 sctx->ctx = ctx;
54 sctx->mech = mechptr;
55 sctx->clientp = clientp;
56
57 if (clientp)
58 {
59 if (sctx->mech->client.start)
60 res = sctx->mech->client.start (sctx, &sctx->mech_data);
61 else if (!sctx->mech->client.step)
62 res = GSASL_NO_CLIENT_CODE;
63 else
64 res = GSASL_OK;
65 }
66 else
67 {
68 if (sctx->mech->server.start)
69 res = sctx->mech->server.start (sctx, &sctx->mech_data);
70 else if (!sctx->mech->server.step)
71 res = GSASL_NO_SERVER_CODE;
72 else
73 res = GSASL_OK;
74 }
75 if (res != GSASL_OK)
76 return res;
77
78 return GSASL_OK;
79 }
80
81 static int
start(Gsasl * ctx,const char * mech,Gsasl_session ** sctx,size_t n_mechs,Gsasl_mechanism * mechs,int clientp)82 start (Gsasl * ctx,
83 const char *mech,
84 Gsasl_session ** sctx,
85 size_t n_mechs, Gsasl_mechanism * mechs, int clientp)
86 {
87 Gsasl_session *out;
88 int res;
89
90 out = calloc (1, sizeof (*out));
91 if (out == NULL)
92 return GSASL_MALLOC_ERROR;
93
94 res = setup (ctx, mech, out, n_mechs, mechs, clientp);
95 if (res != GSASL_OK)
96 {
97 gsasl_finish (out);
98 return res;
99 }
100
101 *sctx = out;
102
103 return GSASL_OK;
104 }
105
106 /**
107 * gsasl_client_start:
108 * @ctx: libgsasl handle.
109 * @mech: name of SASL mechanism.
110 * @sctx: pointer to client handle.
111 *
112 * This functions initiates a client SASL authentication. This
113 * function must be called before any other gsasl_client_*() function
114 * is called.
115 *
116 * Return value: Returns %GSASL_OK if successful, or error code.
117 **/
118 int
gsasl_client_start(Gsasl * ctx,const char * mech,Gsasl_session ** sctx)119 gsasl_client_start (Gsasl * ctx, const char *mech, Gsasl_session ** sctx)
120 {
121 return start (ctx, mech, sctx, ctx->n_client_mechs, ctx->client_mechs, 1);
122 }
123
124 /**
125 * gsasl_server_start:
126 * @ctx: libgsasl handle.
127 * @mech: name of SASL mechanism.
128 * @sctx: pointer to server handle.
129 *
130 * This functions initiates a server SASL authentication. This
131 * function must be called before any other gsasl_server_*() function
132 * is called.
133 *
134 * Return value: Returns %GSASL_OK if successful, or error code.
135 **/
136 int
gsasl_server_start(Gsasl * ctx,const char * mech,Gsasl_session ** sctx)137 gsasl_server_start (Gsasl * ctx, const char *mech, Gsasl_session ** sctx)
138 {
139 return start (ctx, mech, sctx, ctx->n_server_mechs, ctx->server_mechs, 0);
140 }
141