summaryrefslogtreecommitdiff
path: root/source4/rpc_server/dcesrv_crypto.c
blob: 7765815f3bbc9041b0583bbe5c03905628fa00d0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/* 
   Unix SMB/CIFS implementation.

   server side dcerpc authentication code - crypto support

   Copyright (C) Andrew Tridgell 2004
   Copyright (C) Stefan (metze) Metzmacher 2004

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/*
  this provides a crypto interface to the various backends (such as
  NTLMSSP and SCHANNEL) for the rpc server code
*/

#include "includes.h"

/*
  startup the cryptographic side of an authenticated dcerpc server
*/
NTSTATUS dcesrv_crypto_select_type(struct dcesrv_connection *dce_conn,
			       struct dcesrv_auth *auth)
{
	if (auth->auth_info->auth_level != DCERPC_AUTH_LEVEL_INTEGRITY &&
	    auth->auth_info->auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
		DEBUG(2,("auth_level %d not supported in dcesrv auth\n", 
			 auth->auth_info->auth_level));
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (auth->crypto_ctx.ops != NULL) {
		/* TODO:
		 * this this function should not be called
		 * twice per dcesrv_connection!
		 * 
		 * so we need to find out the right
		 * dcerpc error to return
		 */
	}

	/*
	 * TODO:
	 * maybe a dcesrv_crypto_find_backend_by_type() whould be better here
	 * to make thinks more generic
	 */
	auth->crypto_ctx.ops = dcesrv_crypto_backend_bytype(auth->auth_info->auth_type);
	if (auth->crypto_ctx.ops == NULL) {
		DEBUG(2,("dcesrv auth_type %d not supported\n", auth->auth_info->auth_type));
		return NT_STATUS_INVALID_PARAMETER;
	}

	return NT_STATUS_OK;
}

/*
  start crypto state
*/
NTSTATUS dcesrv_crypto_start(struct dcesrv_auth *auth, DATA_BLOB *auth_blob) 
{
	return auth->crypto_ctx.ops->start(auth, auth_blob);
}

/*
  update crypto state
*/
NTSTATUS dcesrv_crypto_update(struct dcesrv_auth *auth, 
			      TALLOC_CTX *out_mem_ctx, 
			      const DATA_BLOB in, DATA_BLOB *out) 
{
	return auth->crypto_ctx.ops->update(auth, out_mem_ctx, in, out);
}

/*
  seal a packet
*/
NTSTATUS dcesrv_crypto_seal(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx,
				uint8_t *data, size_t length, DATA_BLOB *sig)
{
	return auth->crypto_ctx.ops->seal(auth, sig_mem_ctx, data, length, sig);
}

/*
  sign a packet
*/
NTSTATUS dcesrv_crypto_sign(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx,
				const uint8_t *data, size_t length, DATA_BLOB *sig) 
{
	return auth->crypto_ctx.ops->sign(auth, sig_mem_ctx, data, length, sig);
}

/*
  check a packet signature
*/
NTSTATUS dcesrv_crypto_check_sig(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx,
				const uint8_t *data, size_t length, const DATA_BLOB *sig)
{
	return auth->crypto_ctx.ops->check_sig(auth, sig_mem_ctx, data, length, sig);
}

/*
  unseal a packet
*/
NTSTATUS dcesrv_crypto_unseal(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx,
				uint8_t *data, size_t length, DATA_BLOB *sig)
{
	return auth->crypto_ctx.ops->unseal(auth, sig_mem_ctx, data, length, sig);
}

/*
  get the negotiated session key
*/
NTSTATUS dcesrv_crypto_session_key(struct dcesrv_auth *auth, uint8_t session_key[16])
{
	return auth->crypto_ctx.ops->session_key(auth, session_key);
}

/*
  end crypto state
*/
void dcesrv_crypto_end(struct dcesrv_auth *auth) 
{
	auth->crypto_ctx.ops->end(auth);
}

const struct dcesrv_crypto_ops *dcesrv_crypto_backend_bytype(uint8_t auth_type)
{
	switch (auth_type) {
		case DCERPC_AUTH_TYPE_SCHANNEL:
			return dcesrv_crypto_schannel_get_ops();
		case DCERPC_AUTH_TYPE_NTLMSSP:
			return dcesrv_crypto_ntlmssp_get_ops();
	}

	return NULL;
}